用JavaScript读取excel并按列转换为数组

31 篇文章 3 订阅
5 篇文章 0 订阅

首先说一下,ie浏览器有个ActiveXObject的属性,可以很方便的操作excel,网上也有很大教程,就不再赘述了,自行百度。

如果是非ie浏览器的,则需要用到html5的FileReader属性,以及网上的js-xlsx库。微软的xlsx格式本质上是一个zip。而FileReader可以将文件读取成二进制流,通过一定解码即可将zip的二进制流给解析出来,之后的处理sheet以及单元格内容就简单了。如果想要完全自己写,需要对xlsx的压缩编码机制有非常深入的了解。国内网上几乎搜不到半点资料,国外稍有一些,但也不简单,研究起来可能很费时间。国内网上几乎所有的关于用js读取excel的博客都是在用别人的库,而且基本上都是js-xlsx这个库,目前没有找到半篇是真的自己全部撸代码自行解决掉那个zip二进制流解析的部分的。

我向来不反对使用现成的轮子,但是js-xlsx库有点大,即使用js压缩处理也有400k,加上一个jszip大约100k,就需要500k了。这种体积还是比较大的。原本想自行实现解码,或者将js-xlsx中一些不需要的功能给剥离掉,但是时间精力有限,最后就算了,500k就500k吧,这已经算是小的了,如果用到更多的库或者不压缩那还不止。

另外,单页面应用是不推荐使用jquery的,无它,嫌大而已。而且大部分jquery的功能,都可以用zepto.js实现。

先说明一下,本文需用引入两个文件,分别是jszip.js还有xlsx.min.js,可以去github或者gitee上面找js-xlsx的库下载下来,其中的jszip.js还没有经过压缩,可以百度找个在线js代码压缩的网站把代码压缩一下。

接着是我的代码:

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>

<input type="file" id="fileUpload" style="display:none;" onchange="uploadExcel()"/>
<input type="button" id="upload" value="upload" onclick="document.getElementById('fileUpload').click()">

</body>
<script type="text/javascript" src='jszip.min.js'></script>
<script type="text/javascript" src='xlsx.min.js'></script>
<script type="text/javascript">
var id = function(x){return document.getElementById(x);}


function uploadExcel(){
	var fileUpload = id("fileUpload")
	var nameWithPath = fileUpload.value.toLowerCase();

	//用正则表达式校验是否是excel格式的文件
	var regex = /^(.)+(\.xls|\.xlsx)$/;
	
	if(regex.test(nameWithPath)){
		if(typeof(FileReader) != "undefined"){
			var reader = new FileReader();
			// 非ie内核的浏览器
			if(reader.readAsBinaryString){
				reader.readAsBinaryString(fileUpload.files[0]);
				reader.onload = function(e){
					readExcel(e.target.result);
				}
			}
			else{ //高版本的ie内核浏览器
				reader.readAsArrayBuffer(fileUpload.files[0]);
				reader.onload = function(e){
					var data = "";
					var bytes = new Unit8Array(e.target.result);
					for(var i=0;i<bytes.byteLength;i++){
						data += String.fromCharCode(bytes[i]);
					}
					readExcel(data);
				}
			}
		}
		else{
			alert('您的浏览器不支持文件上传功能,建议使用谷歌浏览器');
		}
	}
	else{
		alert('您选择的文件不是excel文件,请重新选择');
	}
}

var columns = [];

function transformLetters(l){
	var ls = {'A':1,'B':2,'C':3,'D':4,'E':5,'F':6,'G':7,'H':8,'I':9,'J':10,'K':11,'L':12,'M':13,'N':14,'O':15,'P':16,'Q':17,'R':18,'S':19,'T':20,'U':21,'V':22,'W':23,'X':24,'Y':25,'Z':26}
	var sum = 0
	while(l.length){
		sum += ls[l[0]]*Math.pow(26,l.length-1)
		l = l.slice(1,l.length)
	}
	return sum
}

function readExcel(data){
	var workbook = XLSX.read(data,{
		type:'binary'
	});

	var sheet0 = workbook.Sheets[workbook.SheetNames[0]];

	var arr = sheet0;

	for(var i in arr){
		if(i.match(/[A-Z]+[0-9]+/g)){
			//column是列
			var column = transformLetters(i.match(/[A-Z]+/g)[0].toUpperCase()) - 1;
			if(columns[column]==undefined){
				columns[column] = [];
			}
			var row = i.match(/[0-9]+/g)[0] - 1;
			columns[column][row] = arr[i].w;
			//t表示内容类型(其中的s表示string,n表示number,b表示boolean,d表示date
			//v表示原始值
			//f表示公式,如B2+C3
			//h表示html内容
			//w格式化后的内容
			//r富文本内容rich text
			//如果没有任何处理的话,w会把数字变成字符串
		}
	}

	console.log(column);
}


</script>
</html>

有几个地方稍作解释,第一是上面的正则表达式,是验证是否为xlsx或xls文件,是再做进一步处理。

第二是这个XLSX库本身不能按列把数据输出来,所以需要进一步处理。先对sheet里面的所有内容用for in 打印出来,判断是否是 字母+数字 的属性名,形如 A1 B3这样的格式,

如果是,则对A1 B3这样的字母加数字拆分并且进行翻译,字母后面的数字就不用说了,就是单元格的行,这个好办,但是ABC这样的字母就要做处理了,如果是只有一个字母的,那么很简单,写一个js hash对象取对应的值就行了,但是我们知道当excel的列多于26的时候就会变成AA,多于702的时候就会变成AAA,以此类推。

本质上就是26进制翻译成10进制嘛,所以我就写了上面那个 transformLetters()的函数将26进制转换成10进制。

上面那个var arr= sheet0这一句其实是多余的,这么写只是自己看起来比较清晰而已,可以改掉。

读取后将值存到一个二维数组里面,就可以进行一系列的处理操作了。

我这里是根据我的业务口径需求按列存储数组,不是说一定要按列,可以自行改成按行处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值