赞
踩
最近接触了一个使用uniapp写的app,其中有个导出Excel的功能,在此做一下总结。
app端生成excel,修改部分单元格参数(文字居中,单元格类型为文本),最后导出.xlsx文件到该app的documents目录下。
在uniapp中导出excel,铺天盖地的都是sheetjs + Blob,然后一顿下载,那是在H5!app里面压根就没有blob对象。(这里引发另一个思考,就是在app端使用webview,这样就能有Blob对象了,没试过,感觉应该是可行的。)
app中,需要使用系统IO流来创建.xlsx文件,然后写入数据。如果写入的是下面的HTML模板,就可以用excel打开了:
let worksheet = "sheet1"; let tableHtml= '<tr><td>姓名</td><td>电话</td><td>邮箱</td></tr>' // 循环遍历,每行加入tr标签,每个单元格加td标签 for (let i = 0; i < jsonData.length; i++) { tableHtml+= '<tr>' for (let item in jsonData[i]) { // 增加\t为了不让表格显示科学计数法或者其他格式 tableHtml += `<td>${jsonData[i][item] + '\t'}</td>` } tableHtml+= '</tr>' } //下载的表格模板数据 let template = `<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"> <head><!--[if gte mso 9]><xml encoding="UTF-8"><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet> <x:Name>${worksheet}</x:Name> <x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet> </x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--> </head><body>${tableHtml}</body></html>`;
先不用急着复制, tableHtml
是可以通过sheetJS转换的,下面会提到,当然你自己循环生成也能用,可以直接看保存的实现。
我们页面中的数据一般都是数组对象类型的,sheetJS可以转换json为html,省去一部分思考。
SheetJS: https://github.com/SheetJS/sheetjs
SheetJS中文文档: https://github.com/rockboom/SheetJS-docs-zh-CN/
SheetJS这个库确实挺牛的,但是它的社区版本不支持修改单元格样式,需要升级到Pro版本,然后就是要你发邮件给作者申请,巴拉巴拉。但是!简单的单元格样式修改是可以通过修改源码来达成的。笔者这里主要是居中对齐和单元格数据类型必须是文本类型,完全够用了。
再来说下xlsx-js-style。
xlsx-js-style : https://github.com/gitbrent/xlsx-js-style
官方的描述是 SheetJS Community Edition
+ Basic Cell Styles
,听起来不错,但是因为app中保存文件的原因,没有采用。
思路是这样的:
先从github上将 xlsx.core.min.js 下载到项目中。
源码中搜索 s[“data-v”] 可以找到需要编辑的位置:
此处新增一行代码:
s["style"] = "text-align: center; mso-number-format:'\@'";
笔者通过观察,发现这里的s就是单元格对象,转化为html时候,s上的属性会被写为单元格的行内式,text-align: center
不用解释了,mso-number-format:'\@'"
意思是将此单元格数据类型设置为自定义类型,值为@
。
有人说,你不是设置成文本类型吗,怎么又弄成自定义类型了。笔者打开excel验证过,当设置一个单元格格式为自定义类型,值为@的时候,再查看该单元格类型,就会自动变为文本类型。
原因我也查过,在excel中@是引用单元格的原文,所以你只写一个@,其实就是原文显示,最终经历了一些不为人知的类型处理,就摇身一变,成了文本类型。感兴趣可以看下这篇文章:Excel自定义格式之“@”符号
数据格式如下:
excelData: [ { no: "1", tag: "weqwrqwrqwrqwrq", remark: "22", }, { no: "2", tag: "342343434343", remark: "33", }, { no: "3", tag: "25125152512", remark: "44", }, ],
转换为html:
const sheet = XLSX.utils.json_to_sheet(this.excelData);
const htmlSheet = XLSX.utils.sheet_to_html(sheet);
这里导出的html是一个完整的包含html标签的字符串,而我们只需要table标签的内容,使用正则提取下:
const pattern = /<table(?:(?!<\/table>).|\n)*?<\/table>/;
const tableHtml = htmlSheet.match(pattern)[0];
最终获取到完整的模板:
const writeData = this.tableToExcel(tableHtml); function tableToExcel(tableHtml) { //列标题 let worksheet = "sheet1"; //下载的表格模板数据 let template = `<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"> <head><!--[if gte mso 9]><xml encoding="UTF-8"><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet> <x:Name>${worksheet}</x:Name> <x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet> </x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--> </head><body>${tableHtml}</body></html>`; return template; },
这里主要使用的是io接口,文档在此:html5plus io文档
保存文件代码如下:
// #ifdef APP-PLUS plus.io.requestFileSystem(plus.io.PUBLIC_DOCUMENTS, function(fs) { let root = fs.root; // 直接在 documents 中创建文件 root.getFile( `${new Date().getTime()}.xlsx`, { create: true, }, (fileEntry) => { fileEntry.createWriter( (writer) => { // 写入数据 writer.write(writeData); // 写入文件成功完成的回调函数 writer.onwrite = (e) => { uni.showToast({ title: `导出成功`, icon: "none", }); }; }, (err) => { console.log(err, "创建文件写入器错误"); } ); }, (err) => { console.log(err); } ); }); // #endif
关于app存储目录的问题,可以看这篇文章: plus.io
io的api一层套一层,需要自己耐心体会,一定可以达到目的!
至此,导出excel功能就收官了!
以上!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。