当前位置:   article > 正文

uniapp 前端导出excel_uni-excel

uni-excel

需求:app前端导出excel,不需要后台参与

方案1:用付费插件(Android读取excel或导出数据到Excel表 - DCloud 插件市场)实操确实可以用,可以设置各种属性,比较齐全

方案2:免费,缺点是有些属性目前不能适配,后续要研究一下,下面写下方案2的流程和代码

一、在comon创建exportExcel.js

  1. // exportExcel.js 可以直接复制
  2. let imgCount = 1;//图片计数器
  3. /**
  4. * 导出Excel
  5. * @param {Object} fileName 文件名 会自动拼接时间戳防止重名
  6. * @param {Object} data 数据内容 格式说明见下
  7. * @param {Object} callback 导出成功的回调方法 返回文件保存路径
  8. *
  9. * 二维数组 其中外层数组中的每个元素为数组 对应一行 内层数组中的每个元素为object对象 对应每个单元格 属性如下:
  10. * type 类型 text为文字 img为图片 默认文字
  11. * width 单元格宽度 请带单位 默认300px
  12. * height 单元格高度 请带单位 默认25px
  13. * color 文字颜色 默认黑色
  14. * fontSize 字号 请带单位 默认16px
  15. * textAlign 文字对齐方式 默认left
  16. * imgWidth 仅type为img时需要 图片宽度 无需带单位 默认25
  17. * imgHeight 仅type为img时需要 图片高度 无需带单位 默认25
  18. * content 单元格内容 type为img时为图片路径 仅支持base64
  19. * colspan 跨列 默认1
  20. * rowspan 跨行 默认1
  21. *
  22. * 示例:
  23. * [
  24. [{
  25. content: '姓名',
  26. color: 'blue',
  27. type: 'text',
  28. width: '200px',
  29. height: '25px',
  30. fontSize: '16px'
  31. }, {
  32. content: '性别',
  33. color: 'blue',
  34. type: 'text',
  35. width: '200px',
  36. height: '25px',
  37. fontSize: '16px'
  38. }, {
  39. content: '头像',
  40. color: 'blue',
  41. type: 'text',
  42. width: '200px',
  43. height: '25px',
  44. fontSize: '16px'
  45. }],
  46. [{
  47. content: '张三',
  48. color: 'blue',
  49. type: 'text',
  50. width: '200px',
  51. height: '25px',
  52. fontSize: '16px',
  53. colspan: 2,
  54. rowspan:2
  55. }, {
  56. content: 'base64图片',
  57. type: 'img',
  58. width: '200px',
  59. height: '25px',
  60. imgWidth: 25,
  61. imgHeight: 25
  62. }],
  63. [{
  64. content: '123',
  65. color: 'blue',
  66. type: 'text',
  67. width: '200px',
  68. height: '25px',
  69. fontSize: '16px'
  70. }]
  71. ]
  72. */
  73. let doExport = function (fileName,data,callback){
  74. imgCount = 1;
  75. let date = new Date();
  76. let year = date.getFullYear();
  77. let month = date.getMonth() + 1;
  78. let day = date.getDate();
  79. let hour = date.getHours();
  80. let minute = date.getMinutes();
  81. let second = date.getSeconds();
  82. if(month < 10){
  83. month = '0' + month;
  84. }
  85. if(day < 10){
  86. day = '0' + day;
  87. }
  88. if(hour < 10){
  89. hour = '0' + hour;
  90. }
  91. if(minute < 10){
  92. minute = '0' + minute;
  93. }
  94. if(second < 10){
  95. second = '0' + second;
  96. }
  97. let name = fileName || '导出的Excel';
  98. let reg = /\\|\//g;
  99. name = name.replace(reg,'|');
  100. name = '' + year + month + day + hour + minute + second + '_' + name;
  101. uni.showLoading({
  102. title: '正在导出',
  103. mask: true
  104. });
  105. formatTable(name,data,callback);
  106. }
  107. async function formatTable(name,data,callback){
  108. let table = `<table style="line-height:3;">`;
  109. for (let item of data) {
  110. table += `<tr>`;
  111. for (let i of item) {
  112. let width = i.width || '70px';
  113. let height = i.height || '25px';
  114. let color = i.color || 'balck';
  115. let fontSize = i.fontSize || '16px';
  116. let textAlign = i.textAlign || 'left';
  117. let border = i.border || 'none';
  118. let colspan = i.colspan || 1;
  119. let rowspan = i.rowspan || 1;
  120. if(i.type==='img'){
  121. let imgWidth = i.imgWidth || 25;
  122. let imgHeight = i.imgHeight || 25;
  123. let src = await saveImg(name,i.content);
  124. console.log(src);
  125. if(src === 'fail'){
  126. uni.hideLoading();
  127. uni.showToast({
  128. title: '导出失败,请确认是否授权文件权限',
  129. icon: 'none'
  130. });
  131. return;
  132. }
  133. table += `<td style="width:${width};height:${height};color:${color};font-size:${fontSize};text-align:${textAlign};border:${border}" colspan="${colspan}" rowspan="${rowspan}"><img src="/图片${imgCount}.jpg" width="${imgWidth}" height="${imgHeight}">(图片${imgCount}.jpg)</td>`;
  134. imgCount ++;
  135. }else{
  136. table += `<td style="width:${width};height:${height};color:${color};font-size:${fontSize};text-align:${textAlign};border:${border};word-wrap:break-word;word-break:break-all;font-family:'宋体'" colspan="${colspan}" rowspan="${rowspan}">${i.content}</td>`;
  137. }
  138. }
  139. table += `</tr>`;
  140. }
  141. table += `</table>`;
  142. exportFile(formatTemplate(table),name,callback);
  143. }
  144. function formatTemplate(data) {
  145. let template = `<html xmlns:o="urn:schemas-microsoft-com:office:office"
  146. xmlns:x="urn:schemas-microsoft-com:office:excel"
  147. xmlns="http://www.w3.org/TR/REC-html40">
  148. <head><!--[if gte mso 9]><xml encoding="UTF-8"><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet>
  149. <x:Name>sheet1</x:Name>
  150. <x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet>
  151. </x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]-->
  152. </head><body>${data}</body></html>`;
  153. return template;
  154. }
  155. function exportFile(fileData,documentName,callback) {
  156. createDir(documentName,(dirEntry,path,name) => {
  157. dirEntry.getFile(`${documentName}.xlsx`, {
  158. create: true
  159. }, (fileEntry) => {
  160. fileEntry.createWriter((writer) => {
  161. writer.onwritestart = (e) => {
  162. console.log('onwritestart');
  163. }
  164. writer.onwrite = (e) => {
  165. // 成功导出数据;
  166. setTimeout(() => {
  167. uni.hideLoading();
  168. uni.showToast({
  169. title: "成功导出",
  170. icon: "success"
  171. });
  172. console.log(`导出成功,文件位置:${path}/${documentName}.xlsx`);
  173. callback(`${path}/${documentName}.xlsx`);
  174. }, 1000);
  175. };
  176. // 写入内容;
  177. writer.write(fileData);
  178. }, function(e) {
  179. console.log(e.message);
  180. uni.hideLoading();
  181. uni.showToast({
  182. title: '导出失败,请确认是否授权文件权限',
  183. icon: 'none'
  184. });
  185. });
  186. },err=>{
  187. console.log(err);
  188. uni.hideLoading();
  189. uni.showToast({
  190. title: '导出失败,请确认是否授权文件权限',
  191. icon: 'none'
  192. });
  193. });
  194. });
  195. }
  196. function saveImg(name,base64){
  197. return new Promise((resolve,reject) => {
  198. createDir(name,(dirEntry,path,name) => {
  199. let bitmap = new plus.nativeObj.Bitmap('图片'+imgCount);
  200. bitmap.loadBase64Data(base64,res => {
  201. console.log(`图片${imgCount}加载base64成功`);
  202. let fileName = '_documents/导出的Excel/' + name + '/图片' + imgCount + '.jpg';
  203. bitmap.save(fileName,{overwrite:true,quality:100,format:'jpg'},res1 => {
  204. console.log(res1);
  205. console.log(`图片${imgCount}保存成功,路径:${fileName}`);
  206. bitmap.clear();
  207. resolve('success');
  208. },err1 => {
  209. console.log(err1);
  210. reject('fail');
  211. });
  212. },err => {
  213. console.log(err);
  214. reject('fail');
  215. });
  216. });
  217. });
  218. }
  219. function createDir(name,callback){
  220. plus.io.requestFileSystem(plus.io.PUBLIC_DOCUMENTS, (fs) => {
  221. let rootObj = fs.root;
  222. let fullPath = rootObj.fullPath;
  223. rootObj.getDirectory('导出的Excel',{create:true},dirEntry => {
  224. dirEntry.getDirectory(name,{create:true},dirEntry2 => {
  225. let pathStr = fullPath.replace("/storage/emulated/0", "");
  226. pathStr += '导出的Excel/'+name;
  227. console.log(`目录${pathStr}创建成功`);
  228. callback(dirEntry2,pathStr,name);
  229. },err2=>{
  230. console.log(err2);
  231. uni.hideLoading();
  232. uni.showToast({
  233. title: '导出失败,请确认是否授权文件权限',
  234. icon: 'none'
  235. });
  236. });
  237. },err1=>{
  238. console.log(err1);
  239. uni.hideLoading();
  240. uni.showToast({
  241. title: '导出失败,请确认是否授权文件权限',
  242. icon: 'none'
  243. });
  244. });
  245. },err=>{
  246. console.log(err);
  247. uni.hideLoading();
  248. uni.showToast({
  249. title: '导出失败,请确认是否授权文件权限',
  250. icon: 'none'
  251. });
  252. });
  253. }
  254. module.exports = doExport;

二、组件中使用

  1. let doExport = require('@/common/exportExcel.js')
  2. import { jsons } from './excelJson.js'
  3. async printingOutline(item) { // 离线导出
  4. //要导出的json数据
  5. const jsonData = JSON.parse(JSON.stringify(jsons))
  6. const that = this
  7. doExport('input', jsonData, function(result){
  8. that.open(result)
  9. })
  10. },
  11. open(url) { // 打开excel
  12. uni.openDocument({
  13. filePath: '/storage/emulated/0'+url, // 要加上前面/storage/emulated/0,不然打不开
  14. success:(res3) =>console.log('成功打开文档'),
  15. fail: (err) => {
  16. console.log('失败')
  17. console.log(err)
  18. }
  19. })
  20. }

excelJson.js

  1. export const jsons = [
  2. [
  3. {
  4. content: '预防控制中心',
  5. type: 'text',
  6. fontSize: '18px',
  7. colspan: 18,
  8. textAlign: 'center',
  9. height: '50px'
  10. }
  11. ],
  12. [
  13. {
  14. content: '采(抽)样登记表',
  15. type: 'text',
  16. fontSize: '18px',
  17. colspan: 18,
  18. textAlign: 'center',
  19. height: '50px'
  20. }
  21. ],
  22. [
  23. {
  24. id: 'test_category',
  25. content: '检验检测类别',
  26. type: 'text',
  27. fontSize: '10px',
  28. colspan: 18,
  29. border: 'solid 1px #000'
  30. }
  31. ],
  32. [
  33. {
  34. id: 'index',
  35. content: '序号',
  36. type: 'text',
  37. fontSize: '10px',
  38. border: 'solid 1px #000'
  39. },
  40. {
  41. id: 'sample_category_text',
  42. content: '样品类别',
  43. type: 'text',
  44. fontSize: '10px',
  45. border: 'solid 1px #000'
  46. },
  47. {
  48. id: 'sample_number',
  49. content: '样品编号',
  50. type: 'text',
  51. fontSize: '10px',
  52. border: 'solid 1px #000'
  53. },
  54. {
  55. id: 'sample_name',
  56. content: '样品名称',
  57. type: 'text',
  58. fontSize: '10px',
  59. },
  60. {
  61. id: 'sample_specifications_text',
  62. content: '样品规格',
  63. type: 'text',
  64. fontSize: '10px',
  65. },
  66. {
  67. id: 'quantity',
  68. content: '数量',
  69. type: 'text',
  70. fontSize: '10px',
  71. },
  72. {
  73. id: 'packaging_type_text',
  74. content: '包装类型',
  75. type: 'text',
  76. fontSize: '10px'
  77. },
  78. {
  79. id: 'sample_trademark',
  80. content: '样品商标',
  81. type: 'text',
  82. fontSize: '10px'
  83. },
  84. {
  85. id: 'packaging_form',
  86. content: '包装形式',
  87. type: 'text',
  88. fontSize: '10px'
  89. },
  90. {
  91. id: 'place_of_origin',
  92. content: '产地',
  93. type: 'text',
  94. fontSize: '10px',
  95. },
  96. {
  97. id: 'manufacturer',
  98. content: '生产厂家(样品来源)',
  99. type: 'text',
  100. fontSize: '10px',
  101. },
  102. {
  103. id: 'manufacturer_address',
  104. content: '生产厂家地址',
  105. type: 'text',
  106. fontSize: '10px',
  107. },
  108. {
  109. id: 'manufacture_date_number',
  110. content: '生产日期/批号',
  111. type: 'text',
  112. fontSize: '10px',
  113. },
  114. {
  115. id: 'sample_character_text',
  116. content: '样品性状',
  117. type: 'text',
  118. fontSize: '10px',
  119. },
  120. {
  121. id: 'storage_condition_text',
  122. content: '保存条件',
  123. type: 'text',
  124. fontSize: '10px',
  125. },
  126. {
  127. id: 'sample_locations',
  128. content: '采样地点',
  129. type: 'text',
  130. fontSize: '10px',
  131. },
  132. {
  133. id: 'sample_locations_type_text',
  134. content: '采样地点类型',
  135. type: 'text',
  136. fontSize: '10px',
  137. },
  138. {
  139. id: 'remark',
  140. content: '备注',
  141. type: 'text',
  142. fontSize: '10px',
  143. }
  144. ]
  145. ]

三、导出结果

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/264086
推荐阅读
相关标签
  

闽ICP备14008679号