导入excel为可在线编辑table并可导出为xlsx格式

导入excel为可在线编辑table并可导出为xlsx格式

此工具参考https://www.jianshu.com/p/31534691ed53并进行了优化。

    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script type="text/javascript" src="http://demo.haoji.me/2017/02/08-js-xlsx/js/xlsx.core.min.js"></script>
    <script type="text/javascript" src="js/colResizable-1.6.min.js"></script>

colResizable-1.6.min.js

官网:http://www.bacubacu.com/colresizable/#samples

下载地址:http://www.bacubacu.com/colresizable/files/colResizable-1.6.zip,此为实现表格列自由拖动,但是动态生成表格后使用后生成表格很慢并且无效,此功能需要广大大佬去优化。

导入表格为table主要实现步骤:

<div id="result" contenteditable="true"></div>

function readWorkbook(workbook) {
		var sheetNames = workbook.SheetNames; // 工作表名称集合
		var worksheet = workbook.Sheets[sheetNames[0]]; // 这里我们只读取第一张sheet
		var html = "\uFEFF"+XLSX.utils.sheet_to_html(worksheet);
		html=html.replace(/<span\s*[^>]*>(.*?)<\/span>/ig,"$1");//正则表达式去除span标签,换行符会导致表格错乱
		$("#result").html(html);//html加载到页面
	}

contenteditable="true"意思是可编辑段落。属性:https://www.runoob.com/tags/att-global-contenteditable.html

 

导出表格为table:

  //导出表格
	function exportExcel() {
		var csv = table2csv($('#result table')[0]);
        var str_csv="\uFEFF"+csv;
        var blob=new Blob([str_csv]);
		openDownloadDialog(blob, '导出.xlsx');
	}
//遍历table的td元素,对csv字符串进行去除空格回车和换行的操作,防止csv转化为xlsx出错
function table2csv(table) {
		var csv = [];
		$(table).find('tr').each(function() {
			var temp = [];	
			$(this).find('td').each(function() {
				temp.push($(this).html().replace(/[\r\n]/g,""));//去掉字符串中的空格回车和换行str=str.replace(/[\r\n]/g,"")
			})
			csv.push(temp.join(','));
		});
		return csv.join('\n');
	}

 

 完整代码:(桌面创建文本文档,重命名为xxx.html,复制粘贴有网络即可使用)


<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
	<title>JS读取和导出excel示例</title>
	<meta name="description" content="使用sheetjs读取和导出excel示例">
    <style type="text/css">
table{
	width:auto;
	border-collapse: collapse;
	table-layout:fixed;/* 只有定义了表格的布局算法为fixed,下面td的定义才能起作用。 */
}
td{
	border:1px solid; 
	height: 30px;
	min-width: 40px;
	font-family:"Trebuchet MS", Helvetica, sans-serif;
	overflow:hidden;		/* 内容超出宽度时隐藏超出部分的内容 */ 
	white-space:nowrap;		/* 不换行 */
	text-overflow:ellipsis;	/* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用*/
}
	.mt-sm {margin-top: 8px;}
	body {
		background: #f4f4f4;
		padding: 0;
		margin: 0;
	}
	.container {
		width: 1024px;
		margin: 0 auto;
		background: #fff;
		padding: 20px;
		min-height: 100vh;
	}
    </style>
</head>
<body>
	<div class="container">
		<h1>JavaScript读取和导出excel示例(基于js-xlsx)</h1>
		<h2>读取excel(仅读取第一个sheet)</h2>
		<div class="mt-sm">
			<input type="file" id="file" style="display:none;" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"/>
			<a href="javascript:selectFile()">加载本地excel文件</a>
			<!-- <a href="javascript:loadRemoteFile('excel/example.xlsx')">加载远程excel文件</a> -->
		</div>
		
		<p>结果输出:(下面表格可直接编辑导出)</p>
		<div id="result" contenteditable="true">
			<table>
				<tr>
					<td>A</td>
					<td>B</td>
					<td>C</td>
					<td>D</td>
				</tr>
				<tr>
					<td>第一列</td>
					<td>A2</td>
					<td>A3</td>
					<td>A4</td>
				</tr>
				<tr>
					<td>B1</td>
					<td>B2</td>
					<td>B3</td>
					<td>B4</td>
				</tr>
			</table>
		</div>

		<h2>导出excel</h2>
		<div class="mt-sm" style="padding-bottom:40px;">
			<input type="button" onclick="exportExcel()" value="保存"/> 上面读取的表格您可以直接编辑,编辑后点击保存即可导出excel文件。
		</div>

		<h2>导出带单元格合并的excel</h2>
		<input type="button" value="导出" onclick="exportSpecialExcel()"/>
	</div>
	<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
	<script type="text/javascript" src="http://demo.haoji.me/2017/02/08-js-xlsx/js/xlsx.core.min.js"></script>
	<!--<script type="text/javascript" src="js/colResizable-1.6.min.js"></script>-->
	<script type="text/javascript">

	function selectFile() {
		document.getElementById('file').click();
	}

	// 读取本地excel文件
	function readWorkbookFromLocalFile(file, callback) {
		var reader = new FileReader();
		reader.onload = function(e) {
			var data = e.target.result;
			var workbook = XLSX.read(data, {type: 'binary'});
			if(callback) callback(workbook);
		};
		reader.readAsBinaryString(file);
	}

	// 从网络上读取某个excel文件,url必须同域,否则报错
	function readWorkbookFromRemoteFile(url, callback) {
		var xhr = new XMLHttpRequest();
		xhr.open('get', url, true);
		xhr.responseType = 'arraybuffer';
		xhr.onload = function(e) {
			if(xhr.status == 200) {
				var data = new Uint8Array(xhr.response)
				var workbook = XLSX.read(data, {type: 'array'});
				if(callback) callback(workbook);
			}
		};
		xhr.send();
	}

	// 读取 excel文件
	function outputWorkbook(workbook) {
		var sheetNames = workbook.SheetNames; // 工作表名称集合
		sheetNames.forEach(name => {
			var worksheet = workbook.Sheets[name]; // 只能通过工作表名称来获取指定工作表
			for(var key in worksheet) {
				// v是读取单元格的原始值
				console.log(key, key[0] === '!' ? worksheet[key] : worksheet[key].v);
			}
		});
	}

	//excel转换为表格主要实现步骤
	function readWorkbook(workbook) {
		var sheetNames = workbook.SheetNames; // 工作表名称集合
		var worksheet = workbook.Sheets[sheetNames[0]]; // 这里我们只读取第一张sheet
		// var csv =XLSX.utils.sheet_to_csv(worksheet);
		// var str_csv=csv.replace("\n","").replace("\n","");
		// document.getElementById('result').innerHTML = csv2table(str_csv);
		var html = "\uFEFF"+XLSX.utils.sheet_to_html(worksheet);
		html=html.replace(/<span\s*[^>]*>(.*?)<\/span>/ig,"$1");//正则表达式去除span标签,换行符会导致表格错乱
		$("#result").html(html);//html加载到页面
	}
//可调整列宽未实现
// $(function(){
// //此处实现表格可拖放属性
//  $("#result table").colResizable({
//     liveDrag:true,//实现实时拖动,可看见拖动轨迹
//     draggingClass:"dragging", //防止拖动出险虚标线
//   });
// });


	// 将csv转换成表格
	function csv2table(csv)
	{
		var html = '<table>';
		var rows = csv.split('\n');
		rows.pop(); // 最后一行没用的
		rows.forEach(function(row, idx) {
			var columns = row.split(',');
			columns.unshift(idx+1); // 添加行索引
			if(idx == 0) { // 添加列索引
				html += '<tr>';
				for(var i=0; i<columns.length; i++) {
					html += '<th>' + (i==0?'':String.fromCharCode(65+i-1)) + '</th>';
				}
				html += '</tr>';
			}
			html += '<tr>';
			columns.forEach(function(column) {
				html += '<td>'+column+'</td>';
			});
			html += '</tr>';
		});
		html += '</table>';
		return html;
	}

	function table2csv(table) {
		var csv = [];
		$(table).find('tr').each(function() {
			var temp = [];	
			$(this).find('td').each(function() {
				temp.push($(this).html().replace(/[\r\n]/g,""));//去掉字符串中的空格回车和换行str=str.replace(/[\r\n]/g,"")
			})
			// temp.shift(); // 移除第一个
			csv.push(temp.join(','));
		});
		// csv.shift();//删除第一个
		return csv.join('\n');
	}

	// csv转sheet对象
	function csv2sheet(csv) {
		var sheet = {}; // 将要生成的sheet
		csv = csv.split('\n');
		csv.forEach(function(row, i) {
			row = row.split(',');
			if(i == 0) sheet['!ref'] = 'A1:'+String.fromCharCode(65+row.length-1)+(csv.length-1);
			row.forEach(function(col, j) {
				sheet[String.fromCharCode(65+j)+(i+1)] = {v: col};
			});
		});
		return sheet;
	}

	// 将一个sheet转成最终的excel文件的blob对象,然后利用URL.createObjectURL下载
	function sheet2blob(sheet, sheetName) {
		sheetName = sheetName || 'sheet1';
		var workbook = {
			SheetNames: [sheetName],
			Sheets: {}
		};
		workbook.Sheets[sheetName] = sheet;
		// 生成excel的配置项
		var wopts = {
			bookType: 'xlsx', // 要生成的文件类型
			bookSST: true, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
			type: 'binary'
		};
		var wbout = XLSX.write(workbook, wopts);
		var blob = new Blob([s2ab(wbout)], {type:"application/octet-stream"});
		// 字符串转ArrayBuffer
		function s2ab(s) {
			var buf = new ArrayBuffer(s.length);
			var view = new Uint8Array(buf);
			for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
			return buf;
		}
		return blob;
	}
    

	/**
	 * 通用的打开下载对话框方法,没有测试过具体兼容性
	 * @param url 下载地址,也可以是一个blob对象,必选
	 * @param saveName 保存文件名,可选
	 */
	function openDownloadDialog(url, saveName)
	{
		if(typeof url == 'object' && url instanceof Blob)
		{
			url = URL.createObjectURL(url); // 创建blob地址
		}
		var aLink = document.createElement('a');
		aLink.href = url;
		aLink.download = saveName || ''; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
		var event;
		if(window.MouseEvent) event = new MouseEvent('click');
		else
		{
			event = document.createEvent('MouseEvents');
			event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
		}
		aLink.dispatchEvent(event);
	}

	$(function() {
		document.getElementById('file').addEventListener('change', function(e) {
			var files = e.target.files;
			if(files.length == 0) return;
			var f = files[0];
			if(!/\.xlsx$/g.test(f.name)) {
				alert('仅支持读取xlsx格式!');
				return;
			}
			readWorkbookFromLocalFile(f, function(workbook) {
				readWorkbook(workbook);
			});
		});
		// loadRemoteFile('./sample/test.xlsx');//自动加载一个远程例子
	});
	
	function loadRemoteFile(url) {
		readWorkbookFromRemoteFile(url, function(workbook) {
			readWorkbook(workbook);
		});
	}
    //导出表格
	function exportExcel() {
		var csv = table2csv($('#result table')[0]);
		// var sheet = csv2sheet(csv);
		// var blob = sheet2blob(sheet);
        var str_csv="\uFEFF"+csv;
        var blob=new Blob([str_csv]);
		openDownloadDialog(blob, '导出.xlsx');
	}
	function exportSpecialExcel() {
		var aoa = [
			['主要信息', null, null, '其它信息'], // 特别注意合并的地方后面预留2个null
			['姓名', '性别', '年龄', '注册时间'],
			['张三', '男', 18, new Date()],
			['李四', '女', 22, new Date()]
		];
		var sheet = XLSX.utils.aoa_to_sheet(aoa);
		sheet['!merges'] = [
			// 设置A1-C1的单元格合并
			{s: {r: 0, c: 0}, e: {r: 0, c: 2}}
		];
		openDownloadDialog(sheet2blob(sheet), '单元格合并示例.xlsx');
	}
	</script>
</body>
</html>

 

 

 

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值