Excel表格插件:js-xlsx.js 的使用

1、描述需求

前两天,有一个需求,excel的某一列中含有不同字符,改为统一字符。如A列(某列)的单元格含有“数字”、“字母”、“商品”、“数字”、“货品”,需求:把“数字”、“字母”改为“ABC123”。


2、寻找插件

从网上搜索到一个插件名为:js-xlsx。其GitHub地址为:https://github.com/SheetJS/js-xlsx

该插件支持IE8及以上版本浏览器,当然还支持safri、firefox、chrome这类优秀浏览器。它提供了脚本js引入npm及bower等模块引入。

3、使用过程

先叙述下我使用它解决那个需求的过程,更多的内容下次分解。

html页面显示如图:


3.1读取表格文件:

<input type="file" accept=".xlsx" id="xlf">

js:

var reader = new FileReader();
var fileExcel={
	"oldFile":"",
};
function addLis() { //监听输入框,引入文件
    var xlf = document.getElementById('xlf');
    if(xlf.addEventListener) xlf.addEventListener('change', handleFile, false);
}

addLis();

// 变量fileExcel赋值,获取文件
function handleFile(e) {
    var files = e.target.files;
    fileExcel.oldFile = files[0];
    readFile(fileExcel.oldFile);
}

function readFile(file) {
    var name = file.name;
    reader.onload = function (e) {
        fileExcel.oldFile = e.target.result;
        var wb = XLSX.read(fileExcel.oldFile, { type: "binary" });
        console.log(wb);
        var wb_sheetname=wb.SheetNames[0];
        console.log(wb.Sheets[wb_sheetname]);
    };
    reader.readAsBinaryString(file);
}

这样,就有了一个全局变量fileExcel,用于存储相关参数,如同vuejs的vuex功能。

3.2 读取第一个工作表

    // 读取文件
    var wb = XLSX.read(fileExcel.oldFile, { type: "binary" });
    // console.log(wb);
    var wb_sheetname=wb.SheetNames[0]; //获取第一张表的名字
    var wb_sheet=wb.Sheets[wb_sheetname]; //通过表名获取第一张表
    // 加入变量
    fileExcel.wb=wb;
    fileExcel.wb_sheetname=wb_sheetname;
    fileExcel.wb_sheet=wb_sheet;
该插件注册了一个全局变量XLSX,提供各种操作。如读取文件接口:
XLSX.read(File, options)

options是解析文件时参数对象,here

这里使用 type:"binary",表示:以字符编码的方式解析。我们可以看到控制台的结果是:


这里可以看到工作簿的详细信息。其中:

SheetNames:由工作簿中工作表的名字组成的数组。

Sheets:包含各工作表的详细内容:


我上传的表格文件中含有3张表,名称分别为:Sheet1、Sheet2、Sheet3。其中!ref表示表格的数据分布范围,是一个字符串类型的数据。有了这个我们在对表格进行各中操作时就有了一个参考。

3.3获取工作表中数据范围

可以通过正则表达式把!ref信息转化为可使用的数据:

    // 开始查询
    var columnNum=$("#queryColumn").val(); //指定查询哪一列
    var columnMax=wb_sheet["!ref"];
    //console.log(columnMax)
    // 匹配数字
    var column_arr=/([A-Z]+)([0-9]+):([A-Z]+)([0-9]+)/i.exec(columnMax)
    console.log(column_arr)

这样,就可以通过数组来操作数据范围了。得到以下结果:


可以看到第一个工作表Sheet1的数据范围是:A列到AD列,1行到12行。得到这个数据可以让我们在进行表格操作时有一个明确的范围,比如查找A列的数据时,只要遍历A1到A12就可以了。

3.4查询数据

在“修改的列名”输入框中键入A,点击查询按钮,得到以下结果:


这里我加入了一段去除重复的代码:

    var arr_sheet_name=[]; //存储列名
    var arr_sheet_value=[]; //存储单元格的内容,不重复
    for(var i=column_arr[2]; i<=column_arr[4]; i++){
    	var column_query_num=columnNum.toString()+i;
    	console.log(wb_sheet[column_query_num])
    	var flag=true; //标记是否可以存储单元格内容,
    	if(wb_sheet[column_query_num]){
    		for(var j=0; j<arr_sheet_value.length; j++){
    			if(arr_sheet_value.length==0){
    				arr_sheet_value.push(wb_sheet[column_query_num].v);
    				arr_sheet_name.push(column_query_num);
    			}
    			if(arr_sheet_value[j]===wb_sheet[column_query_num].v){
    				arr_sheet_name[j]+="_"+column_query_num; //内容重复时,列名存储为:A1_A3
    				flag=false; //单元格内容重复,不存储至arr_sheet_value[]
    				break;
    			}
    		}
    		if(flag){
    			arr_sheet_value.push(wb_sheet[column_query_num].v);
    			arr_sheet_name.push(column_query_num);
    		}
    		flag=true;
    	}
    }

把两个数组显示到页面的第一个大框框中,以备用户选择:

    for (var i = 0; i<=arr_sheet_value.length - 1;  i++) {
    	var stringTag='<div data-inde="'+arr_sheet_name[i]+'" data-value="1" class="one_select">'+arr_sheet_value[i]+'</div>';
    	$("#leftSelect").append(stringTag)
    }
    divfununbind();
    divfunbind();

3.5选择数据进行修改

在左框中点击要修改的内容:


点击 >> 按钮,输入要修改的期望文字:


点击OK按钮,


	// 更改内容
	var change_arr=$("#rightSelect div").map(function() {
		return $(this).attr("data-inde");
	}).get().join("_").split("_"); //获取需要修改的单元格地址
	for(var i=0; i<change_arr.length; i++){
		//fileExcel.wb_sheet[change_arr[i]].h=changeColumn_word;
		//fileExcel.wb_sheet[change_arr[i]].r="<t>"+changeColumn_word+"</t>";
		fileExcel.wb_sheet[change_arr[i]].v=changeColumn_word;
		//fileExcel.wb_sheet[change_arr[i]].w=changeColumn_word;
		console.log(change_arr[i])
		console.log(fileExcel.wb_sheet[change_arr[i]])
	}
	// 全局声明更改表格
	fileExcel.wb.Sheets[fileExcel.wb_sheetname]=fileExcel.wb_sheet;
	console.log(fileExcel.wb_sheet)

更改单元格内容时的操作对象是Sheet[cell]的属性.v,不是Sheet[cell]本身(它的类型是[Object]),

只需更改 .v 的值,因为它指向单元格的值(我猜测此处是引用类型的传值),其他的 .h .r .w 等等都是由它转换而来的。here


我这里把要操作的工作表单独保存为全局变量fileExcel的属性fileExcel.wb_sheet,所以修改数据之后,需要重新给fileExcel.wb.Sheets[fileExcel.wb_sheetname]赋值。

3.6保存工作簿

点击保存按钮,弹出浏览器自带的下载框:


其中的网址是该插件默认的,可以自行修改:

	// /* bookType can be any supported output type */
	// var wopts = { bookType:'xlsx', bookSST:false, type:'array' };
	// var wbout = XLSX.write(fileExcel.wb, wopts);
	// /* the saveAs call downloads a file on the local machine */
	// XLSX.writeFile.saveAs(new Blob([wbout],{type:"application/octet-stream"}), "test.xlsx");

我这里,使用的是:

XLSX.writeFile(fileExcel.wb, 'out.xlsx');

writeFile()接口将自动调用saveAs()。保存文件时,一定要保存工作簿wb,保存工作表wb_sheet是错误的。


4、注意:

该程序有两个bug,因为制作时的目标是:是否有能力实现需求,并没有要求功能十分完整,程序尽可能完美。

第一个bug是:上传文件的input标签,有一个accept属性,给属性只有一个声明功能,并不进行验证。W3C建议进行后台验证。此处如果上传的文件不是Excel是可以上传的。

第二个bug是:输入列名的输入框应该输入规范的列名,如A、AB,如果输入a、Ab、aB或数字或字母与数字的组合是没有结果的。此处应该进行判断和输入有误的提示型告知。

5、关于bug的想法:

软件本没有bug,用的人多了就有了bug。解决bug的第一条思路,鄙人认为是:数据验证、数据约束。

如果不是输入类型的bug,我想也可以从数据约束的思路找到一点点启发。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值