js解析Excel数据

最近做了一个小玩意,邮件群发器,为了让它更易于使用,打算做一个excel上传批量发送的功能,批量发送就不说了,后端直接循环就能达到效果,但是对于excel上传解析这个功能我开始纠结了,并不是说不能做,而是纠结要放在后端做还是放在前端做,之前我也有用php自己玩过excel导入的功能,但是我觉得总是把这些负担施加给服务器不太好,如果我们能放在前端通过js来解析,那么服务器压力会小很多,而且对用户更友好。

既然决定用js来解析excel,我就开始找资料了,因为之前没用js做过这个东西,但是我相信应该能找到我需要的东西,搜索的结果大部分都是说使用Excel.Application这个activex对象来实现,但是activex似乎只有在ie浏览器上面才能使用,但现在用ie的人我相信已经很少了,反正我是从来只用chrome。显然用这个是不行的。最后发现了两个有用的库:

js-xls

js-xlsx

兼容性

支持读取文件格式

Excel 2007+ XML Formats (XLSX/XLSM)

Excel 2007+ Binary Format (XLSB)

Excel 2003-2004 XML Format (XML “SpreadsheetML”)

Excel 97-2004 (XLS BIFF8)

Excel 5.0/95 (XLS BIFF5)

OpenDocument Spreadsheet (ODS)

支持写文件格式

XLSX

CSV (and general DSV)

JSON and JS objects (various styles)

github项目地址:https://github.com/SheetJS/js-xlsx

JS-XLS的安装是很简单的,在浏览器中使用该脚本文件,并使用脚本标记加载它:

<!-- https://github.com/SheetJS/js-xls/blob/master/xls.js -->
<script src="/path/to/xls.js"></script>

对于Node.js,只要通过NPM安装:

$ npm install xlsjs
$ node
> require('xlsjs').readFile('excel_file.xls');

对于JS-JS-XLSX安装和JS-XLS的基本相同。使用浏览器加载jszip.js和xlsx文件:

<!-- https://github.com/SheetJS/js-xlsx/blob/master/jszip.js -->
<script src="/path/to/jszip.js"></script>
<!-- https://github.com/SheetJS/js-xlsx/blob/master/xlsx.js -->
<script src="/path/to/xlsx.js"></script>

对于Node.js,只要通过NPM安装:

$ npm install xlsx
$ node
> require('xlsx').readFile('excel_file.xlsx');

在这里我选择了使用XLSX,毕竟他的兼容性更好。

案例代码:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>excel解析</title>

<style type="text/css">
		.main{
			overflow: hidden;
			margin: 0 0 20px;
		}
		#drop{
			width: 300px;
			height: 200px;
			text-align: center;
			line-height: 200px;
			cursor: pointer;
			border: 3px dashed #f5f5f5;
			float: left;
		}
		#drop.active{
			border-color: #f00;
		}
		#upload{
			display: none;
		}
		#table{
			margin-left: 20px;
			float: left;
		}
		a{
			font-size: 15px;
			text-decoration: none;
			color: #000;
		}
	</style>

</head>
<body>

<div class="main">

<div id="drop">
			点击此处或者将文件拖至此处上传
			<input type="file" id="upload" name="">
		</div>


<div id="table"></div>

	</div>

	<a href="sample.xls" target="_blank">下载样表</a>
	<script type="text/javascript" src="js/jszip.js"></script>
	<script type="text/javascript" src="js/xlsx.js"></script>
	<script type="text/javascript">
		var drop = document.getElementById("drop"),
			upload = document.getElementById("upload"),
			tableC = document.getElementById("table");
			X = XLSX,
			rAbs = typeof FileReader !== "undefined" && typeof FileReader.prototype !== "undefined" && typeof FileReader.prototype.readAsBinaryString !== "undefined";
		drop.addEventListener('click',handleClick,false);
		drop.addEventListener('dragover',handleDragOver,false);
		drop.addEventListener('dragleave',handleDragLeave,false);
		drop.addEventListener('mouseout',handleDragLeave,false);
		drop.addEventListener('drop',function(){
			handleDrop(function(data){
				makeTable(data);
			})
		},false);
		upload.addEventListener('change',function(){
			handleChange(function(data){
				makeTable(data);
			})
		},false);
		function clearTable(){
			tableC.innerHTML = '';
		}
		function makeTable(data){
			clearTable();
			for(var index in data){ //遍历每个表
				var table = document.createElement("table"),
					tr = document.createElement("tr"),
					td = document.createElement("td"),
					keys = Object.keys(data[index][0]);
				td.innerHTML = index + "数据";
				td.colspan = keys.length;
				tr.appendChild(td);
				table.appendChild(tr);
				tr = document.createElement("tr");
				for(var i=0,len=keys.length;i<len;i++){
					td = document.createElement("td");
					td.innerHTML = keys[i];
					tr.appendChild(td);
				}
				table.appendChild(tr);
				for(var i=0,len=data[index].length;i<len;i++){ //循环表中每条数据
					tr = document.createElement("tr")
					var item = data[index][i];
					for(var col in item){
						td = document.createElement("td");
						td.innerHTML = item[col];
						tr.appendChild(td);
					}
					table.appendChild(tr);
				}
				tableC.appendChild(table);
			}
		}
		function handleFile(files,callback){
			var f = files[0],
				reader = new FileReader(),
				name = f.name;
			reader.onload = function(){
				var data = event.target.result,
					wb;
				if(rAbs){
					wb = X.read(data,{type : 'binary'});
				}else{
					var arr = fixData(data);
					wb = X.read(btoa(arr),{type : 'base64'});
				}
				callback && callback(to_json(wb));
			}
			if(rAbs){
				reader.readAsBinaryString(f)
			}else{
				reader.readAsArrayBuffer(f);
			}
			upload.value = '';
		}
		function fixdata(data) {
			var o = "", l = 0, w = 10240;
			for(; l<data.byteLength/w; ++l) o+=String.fromCharCode.apply(null,new Uint8Array(data.slice(l*w,l*w+w))); o+=String.fromCharCode.apply(null, new Uint8Array(data.slice(l*w))); return o; } function to_json(workbook) { var result = {}; workbook.SheetNames.forEach(function(sheetName) { var roa = X.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]); if(roa.length > 0){
					result[sheetName] = roa;
				}
			});
			return result;
		}
		function handleClick(){
			upload.click();
		}
		function handleChange(callback){
			if(upload.value){
				handleFile(event.target.files,callback);
			}
		}
		function handleDrop(callback){
			event.preventDefault();
			event.stopPropagation();
			handleFile(event.dataTransfer.files,callback);
		}
		function handleDragOver(){
			event.preventDefault();
			event.stopPropagation();
			drop.className = 'active';
		}
		function handleDragLeave(){
			drop.className = '';
		}
	</script>
</body>
</html>

在线Demo地址:http://demo.deanhan.cn/XLSX/

  • 支付宝二维码 支付宝
  • 微信二维码 微信
相关文章