前端导出Excel兼容写法
今天整理出在Web前端导出Excel的写法,写了一个工具类,对各个浏览器进行了兼容。
首先,导出的数据来源可能有两种:
1. 页面的HTML内容(一般是table)
2. 纯数据
PS:不同的数据源,导出的写法也是不相同的。
技术方案
IE
无论数据来源是哪里,都是用ActiveXObject对象及相关的命令,IE10、11有点不同。
非IE
纯数据的,使用一个FileSaver.js,如果有浏览器不支持Blob的,还需要引入Blob.js,来做导出。
HTML内容的,构造一个base64字符串的路径,跳转地址下载,其实也可以将数据抽出来,用纯数据的方式。
PS:自行了解Blob对象。
关键问题
1. 非IE导出纯数据中文乱码
解决方法:在Blob的数据要加上"\uFEFF"做修正。
2. Safari的Blob报TypeError: '[object BlobConstructor]' is not a constructor
原因:应该Safari的Blob是不完整的。
解决方法:需要引入一个Blob.js做修正,不过下载的文件会显示"UnKnown",但加上后缀名xls,文件内容还是可以看的(暂时没有很好办法)。
3. Blob每个值是以逗号分隔,那数据有逗号怎么办
解决方法:需要在每个值额外裹上双引号,这样不会影响导出结果,导出内容也是正确的。
4. 非IE导出HTML内容(非table),样式丢失
解决方法:额,这个没有办法,可以将数据抽出来,用纯数据的方式导出。
代码实现
(function(){
var EXCEL_CONTENTTYPE = "application/vnd.ms-excel;",
EXCEL_URI = 'data:application/vnd.ms-excel;base64,',
EXCE_TEMPLATE = '<html><head><meta charset="UTF-8"></head><body>{html}</body></html>',
__PREVFIX = "\uFEFF",
ieVersion = window.navigator.userAgent.toLowerCase().match(/(msie\s|trident.*rv:)([\w.]+)/),
useIE = ieVersion && ieVersion[2] < 10,
isIE1011 = ieVersion && ieVersion[2] > 9;
var Export = {
/*
*@param datas Two-dimensional array : datas, export only with data
or String : DOM id, export html content
*@param fileName export file name
*/
toExcel: function(datas, fName){
var isId = typeof datas === 'string';
if(isId || datas instanceof Array){
if(useIE || isId && isIE1011){
Export.__ieExport(datas);
} else{
Export.__oTherExport(datas, fName);
}
} else{
alert("datas params need Two-dimensional array or String.");
}
},
__ieExport : function(datas){
var oXL = new ActiveXObject("Excel.Application"),
oWB = oXL.Workbooks.Add(),
oSheet = oWB.ActiveSheet,
i = 0,
j;
if(typeof datas === 'string'){
var elem = document.getElementById(datas);
var sel = document.body.createTextRange();
sel.moveToElementText(elem);
try{
sel.select();
//there ie10、11 will be error, i don't know why, but also can export
} catch(e){}
sel.execCommand("Copy");
oSheet.Paste();
} else {
for(; i < datas.length; i++){
var row = datas[i];
for (j = 0; j < row.length; j++) {
oSheet.Cells(i + 1, j + 1).value = row[j];
}
}
}
oXL.Visible = true;
},
__oTherExport : function(datas, fileName){
if(typeof datas === 'string'){
var elem = document.getElementById(datas),
content = EXCE_TEMPLATE.replace("{html}", elem.outerHTML);
//TODO: need test large amount of data
window.location.href = EXCEL_URI +
window.btoa(unescape(encodeURIComponent(content)));
} else {
var blob,
i = 0,
j,
str = __PREVFIX;
for(; i < datas.length; i++){
var row = datas[i];
// the value add double quotation marks on both sides, for separate values.
str += "\""+ row.join("\",\"") + "\"\n";
}
//on safari: TypeError: '[object BlobConstructor]' is not a constructor (evaluating 'new Blob([str],{
//import Blob.js to fix, but still have a problem : the fileName will be 'Unknown' ,
//but if you add suffix name, content can be seen.
blob = new Blob([str],{
type: EXCEL_CONTENTTYPE
});
saveAs(blob, fileName || "Download.xls");
}
}
}
window.ExportUtil = Export;
})();
演示示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>demo</title>
<style type="text/css">
ul{ list-style:none; padding:0px; margin:0px; width:590px;
height:20px; line-height:20px; border:1px solid #99CC00;
border-top:0px; font-size:12px;}
ul li{ display:block; width:33%; float:left;text-indent:2em}
.th{ background:#F1FADE; font-weight:bold; border-top:1px }
</style>
</head>
<body>
<div>
<table id="tb" border=4 width=250 align=center>
<caption>【表格举例】</caption>
<tr bgcolor="#cccccc">
<th><br></th>
<th>列-A</th>
<th>列-B</th>
<th>列-C</th>
</tr>
<tr align=center>
<td>行-1</td>
<td>A1</td>
<td>B1</td>
<td rowspan=2>C1-C2</td>
</tr>
<tr align=center>
<td>行-2</td>
<td>A2</td>
<td>B2</td>
</tr>
<tr align=center>
<td>行-3</td>
<td>A3</td>
<td colspan=2>A3-B3</td>
</tr>
</table> <div id="tul">
<h1><a href="http://www.66css.com">www.66css.com</a></h1>
<ul class="th">
<li>姓名</li>
<li>班级</li>
<li>年龄</li>
</ul>
<ul>
<li>阿三</li>
<li>3-1</li>
<li>13</li>
</ul>
<ul>
<li>小龙</li>
<li>2-4</li>
<li>16</li>
</ul>
<ul>
<li>大马</li>
<li>5-3</li>
<li>17</li>
</ul>
</div>
<script src="Blob.js"></script>
<script src="FileSaver.min.js"></script>
<script src="ExportUtil.js"></script><!--工具类-->
<script>
//demo 1
ExportUtil.toExcel([
["学号", "姓名", "年龄"],
["001", "张学友", "40"],
["002", "张信哲", "38"],
["003", "林志炫", "41"],
["004", "刘亦菲", "24"],
["005", "贾玲", "30"],
["006", "陈一发", "23"]
],"hello.xls"); //demo2
ExportUtil.toExcel("tb"); //demo3
ExportUtil.toExcel("tul");
//ie的有样式,但某些样式会丢失。
</script>
</body>
</html>
代码下载
我将完整代码放这:https://github.com/codingforme/code-learn/tree/master/export-excel
总结
这个导出Excel工具类兼容了Chrome、Firefox、Safari(不完美)、IE6-11,针对两种数据源都做了处理。一般来说,纯数据导出的效果是最好的,所以如果HTML内容导出方式不满意,可以将数据抽出,用回纯数据导出。最后,这个工具缺失的是对大数据量导出的测试,不过这个后面有空再进行验证。
本文为原创文章,转载请保留原出处,方便溯源,如有错误地方,谢谢指正。
前端导出Excel兼容写法的更多相关文章
- js前端导出excel
此例子是利用html特性,纯前端导出excel,样式不好看,兼容主流浏览器. var tableid = jQuery(this).closest("div.tab-label-wrap&q ...
- 前端导出excel表
前端导出excel表 方式一: 前端js实现 : https://www.cnblogs.com/zhangym118/p/6235801.html 方式二: java后端实现: https://bl ...
- 前端导出Excel
1.首先,需要下载一个叫better-xlsx,的插件,以yarn 为例 ' yarn add better-xlsx --save '下载相关依赖包( npm 方式 ' npm i better-x ...
- 踹掉后端,前端导出Excel!
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一个下载链接,但有时候我们只想导出前端页面上已经有了的数据,不想再调后端导出接口浪费服务器资源,学习本文demo例子,我们踹掉后端,直接在前 ...
- vue项目,前端导出excel
今天研究一下前端如何导出excel,边查边实践,边记录 1.安装依赖库 xlsx:这是一个功能强大的excel处理库,但是上手难度也很大,还涉及不少二进制的东西 file-saver:ES5新增了相关 ...
- vue 纯前端导出 excel 表格
在开发后台管理系统的时候,很多地方都要用到导出excel 表格,比如将table中的数据导出到本地,那么实现这种需求往往有两种方案: 一.后端开发一个下载链接,前端将这个链接放到 a 标签的 href ...
- 前端导出excel数据-jsonToExcel
咳咳,好久没有写博了... 在工作中遇到了纯前端,将数据导出为excel文件.正文开始: 第一步 安装依赖: npm i xlsx 第二步 写导出函数: import XLSX from 'xlsx' ...
- JS导出excel 兼容ie、chrome、firefox
运用js实现将页面中的table导出为excel文件,页面显示如下: 导出的excel文件显示如下: 实现代码: <!DOCTYPE html> <html> <head ...
- js前端导出excel:json形式的导出
第一中形式的导出:主要是表头对应主体数据,json形式的导出 js库文件名称 : table2excel.js这个js库文件是网上找的,并且自己根据自己业务需求把内容改了一下复制到 table2exc ...
随机推荐
- codevs 3289 花匠
题目:codevs 3289 花匠 链接:http://codevs.cn/problem/3289/ 这道题有点像最长上升序列,但这里不是上升,是最长"波浪"子序列.用动态规划可 ...
- Web前端温故知新-CSS基础
一.CSS定义与编写CSS 1.1 CSS的定义 全名:Cascading Style Sheets -> 层叠样式表 定义:CSS成为层叠样式表,它主要用于设置HTML页面中的文本内容(字体. ...
- HTML5笔记:跨域通讯、多线程、本地存储和多图片上传技术
最近做项目在前端我使用了很多新技术,这些技术有bootstrap.angularjs,不过最让我兴奋的还是使用了HTML5的技术,今天我想总结一些HTML5的技术,好记性不如烂笔头,写写文章可以很好的 ...
- 借助Nodejs探究WebSocket
文章导读: 一.概述-what's WebSocket? 二.运行在浏览器中的WebSocket客户端+使用ws模块搭建的简单服务器 三.Node中的WebSocket 四.socket.io 五.扩 ...
- ASP.NET MVC Model验证(二)
ASP.NET MVC Model验证(二) 前言 上篇内容演示了一个简单的Model验证示例,然后在文中提及到Model验证在MVC框架中默认所处的位置在哪?本篇就是来解决这个问题的,并且会描述一下 ...
- ABP源码分析四十五:ABP ZERO中的EntityFramework模块
AbpZeroDbContext:配置ABP.Zero中定义的entity的Dbset EntityFrameworkModelBuilderExtensions:给PrimitiveProperty ...
- Entity Framework 6 Recipes 2nd Edition(9-1)译->用Web Api更新单独分离的实体
第九章 在N层结构的应用程序中使用EF 不是所有的应用都能完全地写入到一个单个的过程中(就是驻留在一个单一的物理层中),实际上,在当今不断发展的网络世界,大量的应用程序的结构包含经典的表现层,应用程, ...
- [翻译]AKKA笔记 -ACTOR SUPERVISION - 8
失败更像是分布式系统的一个特性.因此Akka用一个容忍失败的模型,在你的业务逻辑与失败处理逻辑(supervision逻辑)中间你能有一个清晰的边界.只需要一点点工作,这很赞.这就是我们要讨论的主题. ...
- ASP.NET AntiXSS的使用
下载类库: http://wpl.codeplex.com 添加程序集引用 在web.config文件中将AntiXSS类库注册为应用程序的编码器 在<system.web& ...
- Javascript 中 with 的替代方案和String 中的正则方法
这几天在升级自己的MVVM 框架,遇到很多小问题,就在这里统一解决了. with 语法 在代码中,要执行这么一个函数 function computeExpression(exp, scope) { ...