原文:Converting an Ext 5 Grid to Excel Spreadsheet

稍微迟来的礼物——Ext JS Grid转为Excel代码,现在支持Ext JS 5!

功能包括:

- 支持分组

- 数字的处理 VS 字符串数据类型

- 对于不支持客户端下载的浏览器会提交回服务器

Enjoy!

/*

    Excel.js - convert an ExtJS 5 grid into an Excel spreadsheet using nothing but
javascript and good intentions. By: Steve Drucker
Dec 26, 2014
Original Ext 3 Implementation by: Nige "Animal" White? Contact Info: e. sdrucker@figleaf.com
blog: druckit.wordpress.com
linkedin: www.linkedin.com/in/uberfig
git: http://github.com/sdruckerfig
company: Fig Leaf Software (http://www.figleaf.com / http://training.figleaf.com) Invocation: grid.downloadExcelXml(includeHiddenColumns,title) Upgraded for ExtJS5 on Dec 26, 2014 */ var Base64 = (function() {
// Private property
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; // Private method for UTF-8 encoding function utf8Encode(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;
} // Public method for encoding
return {
encode: (typeof btoa == 'function') ? function(input) {
return btoa(utf8Encode(input));
} : function(input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = utf8Encode(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 +
keyStr.charAt(enc1) + keyStr.charAt(enc2) +
keyStr.charAt(enc3) + keyStr.charAt(enc4);
}
return output;
}
};
})(); Ext.define('MyApp.overrides.view.Grid', {
override: 'Ext.grid.GridPanel',
requires: 'Ext.form.action.StandardSubmit', /*
Kick off process
*/ downloadExcelXml: function(includeHidden, title) { if (!title) title = this.title; var vExportContent = this.getExcelXml(includeHidden, title); /*
dynamically create and anchor tag to force download with suggested filename
note: download attribute is Google Chrome specific
*/ if (Ext.isChrome) {
var gridEl = this.getEl();
var location = 'data:application/vnd.ms-excel;base64,' + Base64.encode(vExportContent); var el = Ext.DomHelper.append(gridEl, {
tag: "a",
download: title + "-" + Ext.Date.format(new Date(), 'Y-m-d Hi') + '.xls',
href: location
}); el.click(); Ext.fly(el).destroy(); } else { var form = this.down('form#uploadForm');
if (form) {
form.destroy();
}
form = this.add({
xtype: 'form',
itemId: 'uploadForm',
hidden: true,
standardSubmit: true,
url: 'http://webapps.figleaf.com/dataservices/Excel.cfc?method=echo&mimetype=application/vnd.ms-excel&filename=' + escape(title + ".xls"),
items: [{
xtype: 'hiddenfield',
name: 'data',
value: vExportContent
}]
}); form.getForm().submit(); }
}, /* Welcome to XML Hell
See: http://msdn.microsoft.com/en-us/library/office/aa140066(v=office.10).aspx
for more details */
getExcelXml: function(includeHidden, title) { var theTitle = title || this.title; var worksheet = this.createWorksheet(includeHidden, theTitle);
if (this.columnManager.columns) {
var totalWidth = this.columnManager.columns.length;
} else {
var totalWidth = this.columns.length;
} return ''.concat(
'<?xml version="1.0"?>',
'<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">',
'<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"><Title>' + theTitle + '</Title></DocumentProperties>',
'<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office"><AllowPNG/></OfficeDocumentSettings>',
'<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">',
'<WindowHeight>' + worksheet.height + '</WindowHeight>',
'<WindowWidth>' + worksheet.width + '</WindowWidth>',
'<ProtectStructure>False</ProtectStructure>',
'<ProtectWindows>False</ProtectWindows>',
'</ExcelWorkbook>', '<Styles>', '<Style ss:ID="Default" ss:Name="Normal">',
'<Alignment ss:Vertical="Bottom"/>',
'<Borders/>',
'<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#000000"/>',
'<Interior/>',
'<NumberFormat/>',
'<Protection/>',
'</Style>', '<Style ss:ID="title">',
'<Borders />',
'<Font ss:Bold="1" ss:Size="18" />',
'<Alignment ss:Horizontal="Center" ss:Vertical="Center" ss:WrapText="1" />',
'<NumberFormat ss:Format="@" />',
'</Style>', '<Style ss:ID="headercell">',
'<Font ss:Bold="1" ss:Size="10" />',
'<Alignment ss:Horizontal="Center" ss:WrapText="1" />',
'<Interior ss:Color="#A3C9F1" ss:Pattern="Solid" />',
'</Style>', '<Style ss:ID="even">',
'<Interior ss:Color="#CCFFFF" ss:Pattern="Solid" />',
'</Style>', '<Style ss:ID="evendate" ss:Parent="even">',
'<NumberFormat ss:Format="yyyy-mm-dd" />',
'</Style>', '<Style ss:ID="evenint" ss:Parent="even">',
'<Numberformat ss:Format="0" />',
'</Style>', '<Style ss:ID="evenfloat" ss:Parent="even">',
'<Numberformat ss:Format="0.00" />',
'</Style>', '<Style ss:ID="odd">',
'<Interior ss:Color="#CCCCFF" ss:Pattern="Solid" />',
'</Style>', '<Style ss:ID="groupSeparator">',
'<Interior ss:Color="#D3D3D3" ss:Pattern="Solid" />',
'</Style>', '<Style ss:ID="odddate" ss:Parent="odd">',
'<NumberFormat ss:Format="yyyy-mm-dd" />',
'</Style>', '<Style ss:ID="oddint" ss:Parent="odd">',
'<NumberFormat Format="0" />',
'</Style>', '<Style ss:ID="oddfloat" ss:Parent="odd">',
'<NumberFormat Format="0.00" />',
'</Style>', '</Styles>',
worksheet.xml,
'</Workbook>'
);
}, /* Support function to return field info from store based on fieldname */ getModelField: function(fieldName) { var fields = this.store.model.getFields();
for (var i = 0; i < fields.length; i++) {
if (fields[i].name === fieldName) {
return fields[i];
}
}
}, /* Convert store into Excel Worksheet */
generateEmptyGroupRow: function(dataIndex, value, cellTypes, includeHidden) { var cm = this.columnManager.columns;
var colCount = cm.length;
var rowTpl = '<Row ss:AutoFitHeight="0"><Cell ss:StyleID="groupSeparator" ss:MergeAcross="{0}"><Data ss:Type="String"><html:b>{1}</html:b></Data></Cell></Row>';
var visibleCols = 0; // rowXml += '<Cell ss:StyleID="groupSeparator">' for (var j = 0; j < colCount; j++) {
if (cm[j].xtype != 'actioncolumn' && (cm[j].dataIndex != '') && (includeHidden || !cm[j].hidden)) {
// rowXml += '<Cell ss:StyleID="groupSeparator"/>';
visibleCols++;
}
} // rowXml += "</Row>"; return Ext.String.format(rowTpl, visibleCols - 1, Ext.String.htmlEncode(value));
}, createWorksheet: function(includeHidden, theTitle) {
// Calculate cell data types and extra class names which affect formatting
var cellType = [];
var cellTypeClass = [];
console.log(this);
if (this.columnManager.columns) {
var cm = this.columnManager.columns;
} else {
var cm = this.columns;
}
console.log(cm);
var colCount = cm.length;
var totalWidthInPixels = 0;
var colXml = '';
var headerXml = '';
var visibleColumnCountReduction = 0; for (var i = 0; i < cm.length; i++) {
if (cm[i].xtype != 'actioncolumn' && (cm[i].dataIndex != '') && (includeHidden || !cm[i].hidden)) {
var w = cm[i].getEl().getWidth();
totalWidthInPixels += w; if (cm[i].text === "") {
cellType.push("None");
cellTypeClass.push("");
++visibleColumnCountReduction;
} else {
colXml += '<Column ss:AutoFitWidth="1" ss:Width="' + w + '" />';
headerXml += '<Cell ss:StyleID="headercell">' +
'<Data ss:Type="String">' + cm[i].text.replace("<br>"," ") + '</Data>' +
'<NamedCell ss:Name="Print_Titles"></NamedCell></Cell>'; var fld = this.getModelField(cm[i].dataIndex); switch (fld.$className) {
case "Ext.data.field.Integer":
cellType.push("Number");
cellTypeClass.push("int");
break;
case "Ext.data.field.Number":
cellType.push("Number");
cellTypeClass.push("float");
break;
case "Ext.data.field.Boolean":
cellType.push("String");
cellTypeClass.push("");
break;
case "Ext.data.field.Date":
cellType.push("DateTime");
cellTypeClass.push("date");
break;
default:
cellType.push("String");
cellTypeClass.push("");
break;
}
}
}
}
var visibleColumnCount = cellType.length - visibleColumnCountReduction; var result = {
height: 9000,
width: Math.floor(totalWidthInPixels * 30) + 50
}; // Generate worksheet header details. // determine number of rows
var numGridRows = this.store.getCount() + 2;
if ((this.store.groupField &&!Ext.isEmpty(this.store.groupField)) || (this.store.groupers && this.store.groupers.items.length > 0)) {
numGridRows = numGridRows + this.store.getGroups().length;
} // create header for worksheet
var t = ''.concat(
'<Worksheet ss:Name="' + theTitle + '">', '<Names>',
'<NamedRange ss:Name="Print_Titles" ss:RefersTo="=\'' + theTitle + '\'!R1:R2">',
'</NamedRange></Names>', '<Table ss:ExpandedColumnCount="' + (visibleColumnCount + 2),
'" ss:ExpandedRowCount="' + numGridRows + '" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="65" ss:DefaultRowHeight="15">',
colXml,
'<Row ss:Height="38">',
'<Cell ss:MergeAcross="' + (visibleColumnCount - 1) + '" ss:StyleID="title">',
'<Data ss:Type="String" xmlns:html="http://www.w3.org/TR/REC-html40">',
'<html:b>' + theTitle + '</html:b></Data><NamedCell ss:Name="Print_Titles">',
'</NamedCell></Cell>',
'</Row>',
'<Row ss:AutoFitHeight="1">',
headerXml +
'</Row>'
); // Generate the data rows from the data in the Store
var groupVal = "";
var groupField = "";
if (this.store.groupers && this.store.groupers.keys.length > 0) {
groupField = this.store.groupers.keys[0];
} else if (this.store.groupField != '') {
groupField = this.store.groupField;
} for (var i = 0, it = this.store.data.items, l = it.length; i < l; i++) { if (!Ext.isEmpty(groupField)) {
if (groupVal != this.store.getAt(i).get(groupField)) {
groupVal = this.store.getAt(i).get(groupField);
t += this.generateEmptyGroupRow(groupField, groupVal, cellType, includeHidden);
}
}
t += '<Row>';
var cellClass = (i & 1) ? 'odd' : 'even';
r = it[i].data;
var k = 0;
for (var j = 0; j < colCount; j++) {
if (cm[j].xtype != 'actioncolumn' && (cm[j].dataIndex != '') && (includeHidden || !cm[j].hidden)) {
var v = r[cm[j].dataIndex];
if (cellType[k] !== "None") {
t += '<Cell ss:StyleID="' + cellClass + cellTypeClass[k] + '"><Data ss:Type="' + cellType[k] + '">';
if (cellType[k] == 'DateTime') {
t += Ext.Date.format(v, 'Y-m-d');
} else {
t += Ext.String.htmlEncode(v);
}
t += '</Data></Cell>';
}
k++;
}
}
t += '</Row>';
} result.xml = t.concat(
'</Table>',
'<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">',
'<PageLayoutZoom>0</PageLayoutZoom>',
'<Selected/>',
'<Panes>',
'<Pane>',
'<Number>3</Number>',
'<ActiveRow>2</ActiveRow>',
'</Pane>',
'</Panes>',
'<ProtectObjects>False</ProtectObjects>',
'<ProtectScenarios>False</ProtectScenarios>',
'</WorksheetOptions>',
'</Worksheet>'
);
return result;
}
});

附:在原文底部有Ext JS 4版本的链接

【翻译】将Ext JS Grid转换为Excel表格的更多相关文章

  1. 【面试题】js实现将excel表格copy到页面

    js实现将excel表格copy到页面 点击打开视频讲解更加详细 其实最核心的技术,还是copy的是我们粘贴板上的数据 就像平常怎么粘贴复制其他的数据一样,只是我们在excel粘贴的是一个表格数据 这 ...

  2. 【翻译】Ext JS 6.2 早期访问版本发布

    原文:Announcing Ext JS 6.2 Early Access 非常开心,Sencha Ext JS 6.2早期访问版本今天发布了.早期访问版本的主要目的是为了让大家进行测试并评估Ext ...

  3. 【翻译】Ext JS——高效的编码风格指南

    原文:ExtJS - Efficient coding style guide 作者:Raja 切勿使用"new"关键字:在Ext JS中,使用"new"关键字 ...

  4. 【翻译】Ext JS最新技巧——2016-3-4

    原文:Top Support Tips Kevin Cassidy:Grid水印 Ext JS的Grid是一个便于在布局中显示信息的伟大工具.有些用户可能会希望将这些信息打印为会议资料或宣传材料,而且 ...

  5. 【翻译】Ext JS最新技巧——2015-10-21

    原文:Top Support Tips Kevin Cassidy:全宽度的字段错误信息 有考虑过让验证信息显示在表单字段的下面(msgTarget:'under'),但最后发现验证信息被压缩显示了吗 ...

  6. 【翻译】Ext JS 6 Beta发布

    原文:Ext JS 6 Beta is Now Available 概述 Ext JS 6的好处 新的Ext JS功能和工具 需要你的反馈意见 概述 很高兴,Ext JS 6 beta版本现在发布了. ...

  7. 【翻译】Ext JS 6早期访问版本发布

    早期访问版本是什么 如何参与 都包括什么 Sencha Ext JS 6 Sencha Pivot Grid Sencha Cmd 6 JetBrains IDE插件 反馈 原文:Announcing ...

  8. 【翻译】Ext JS最新技巧——2014-8-13

    原文:Top Support Tips Greg Barry:新的框架. 新的文档类型(Doctype) 在Ext JS 5,只支持IE8+,因此不再古力用户使用严格的HTML文档类型.现在,推荐使用 ...

  9. 【翻译】Ext JS 5的平板支持

    原文:Ext JS 5 Tablet Support Ext JS已被公认为桌面Web应用程序的领先框架.自从平板开始在全球挑战PC的销售,无论是个人还是企业,电脑横向的应用已经产生急剧的变化.Sen ...

随机推荐

  1. 软件测试assert

    之前实习做过一段时间测试,现做个总结: 实习测试的是一款CM系统(case 系统),来记录IT部门处理的维修,服务,反馈,预定服务等case:b/s架构,人少小项目,实习时间短,去了已经快完工,主要测 ...

  2. spark升级后 集成hbase-1.0.0-cdh5.4.5异常

    .具体场景如下: spark1.6  升级  spark2.2 后    分析查询hbase  数据报异常: 具体错误如下:       ERROR TableInputFormat: java.io ...

  3. MongoDB 固定集合

    MongoDB 固定集合(Capped Collections)是性能出色且有着固定大小的集合,对于大小固定,我们可以想象其就像一个环形队列,当集合空间用完后,再插入的元素就会覆盖最初始的头部的元素! ...

  4. Ubuntu批量修改文件名后缀

    比如把当前文件夹下所有scss文件后缀改为less rename 's/\.scss/\.less/' ./*

  5. Dynamics CRM build numbers

    Dynamics CRM build numbers CRM各大版本及补丁列表,整理的很全

  6. Swift基础之自定义PUSH和POP跳转动画

    之前用OC代码写过PUSH和POP的转场动画,闲来无事,将其转换成Swift语言,希望对大家有帮助,转载请注明.... 如何实现PUSH和POP的转场动画? 首先,创建一个NSObject的类,分别用 ...

  7. Android双击退出

    重写返回键 private long tempTime = 0; /** * 双击退出 */ @Override public void onBackPressed() { long firstCli ...

  8. Dynamics CRM2016 Web API之Use custom FetchXML

    CRM2016中新增的web api支持fetch xml了,之前使用FetchXML的场景是在后天代码中通过组织服务的retrieve multiple方法,但实际的应用效果有多大,还需要在实际的项 ...

  9. Universal-Image-Loader 图片异步加载类库的使用

    这个图片异步加载并缓存的类已经被很多开发者所使用,是最常用的几个开源库之一,主流的应用,随便反编译几个火的项目,都可以见到它的身影. 可是有的人并不知道如何去使用这库如何进行配置,网上查到的信息对于刚 ...

  10. FORM当前状态分析

     变量  SYSTEM.RECORD_STATUS 确定当前记录状态.有四种返回值:CHANGED表示记录从数据库取来,并且该记录至少一个基表列被更新:INSERT表示给一个非取自数据库记录的基表 ...