赞
踩
需求:app前端导出excel,不需要后台参与
方案1:用付费插件(Android读取excel或导出数据到Excel表 - DCloud 插件市场)实操确实可以用,可以设置各种属性,比较齐全
方案2:免费,缺点是有些属性目前不能适配,后续要研究一下,下面写下方案2的流程和代码
一、在comon创建exportExcel.js
- // exportExcel.js 可以直接复制
- let imgCount = 1;//图片计数器
-
- /**
- * 导出Excel
- * @param {Object} fileName 文件名 会自动拼接时间戳防止重名
- * @param {Object} data 数据内容 格式说明见下
- * @param {Object} callback 导出成功的回调方法 返回文件保存路径
- *
- * 二维数组 其中外层数组中的每个元素为数组 对应一行 内层数组中的每个元素为object对象 对应每个单元格 属性如下:
- * type 类型 text为文字 img为图片 默认文字
- * width 单元格宽度 请带单位 默认300px
- * height 单元格高度 请带单位 默认25px
- * color 文字颜色 默认黑色
- * fontSize 字号 请带单位 默认16px
- * textAlign 文字对齐方式 默认left
- * imgWidth 仅type为img时需要 图片宽度 无需带单位 默认25
- * imgHeight 仅type为img时需要 图片高度 无需带单位 默认25
- * content 单元格内容 type为img时为图片路径 仅支持base64
- * colspan 跨列 默认1
- * rowspan 跨行 默认1
- *
- * 示例:
- * [
- [{
- content: '姓名',
- color: 'blue',
- type: 'text',
- width: '200px',
- height: '25px',
- fontSize: '16px'
- }, {
- content: '性别',
- color: 'blue',
- type: 'text',
- width: '200px',
- height: '25px',
- fontSize: '16px'
- }, {
- content: '头像',
- color: 'blue',
- type: 'text',
- width: '200px',
- height: '25px',
- fontSize: '16px'
- }],
- [{
- content: '张三',
- color: 'blue',
- type: 'text',
- width: '200px',
- height: '25px',
- fontSize: '16px',
- colspan: 2,
- rowspan:2
- }, {
- content: 'base64图片',
- type: 'img',
- width: '200px',
- height: '25px',
- imgWidth: 25,
- imgHeight: 25
- }],
- [{
- content: '123',
- color: 'blue',
- type: 'text',
- width: '200px',
- height: '25px',
- fontSize: '16px'
- }]
- ]
- */
- let doExport = function (fileName,data,callback){
- imgCount = 1;
- let date = new Date();
- let year = date.getFullYear();
- let month = date.getMonth() + 1;
- let day = date.getDate();
- let hour = date.getHours();
- let minute = date.getMinutes();
- let second = date.getSeconds();
- if(month < 10){
- month = '0' + month;
- }
- if(day < 10){
- day = '0' + day;
- }
- if(hour < 10){
- hour = '0' + hour;
- }
- if(minute < 10){
- minute = '0' + minute;
- }
- if(second < 10){
- second = '0' + second;
- }
- let name = fileName || '导出的Excel';
- let reg = /\\|\//g;
- name = name.replace(reg,'|');
- name = '' + year + month + day + hour + minute + second + '_' + name;
- uni.showLoading({
- title: '正在导出',
- mask: true
- });
- formatTable(name,data,callback);
- }
-
- async function formatTable(name,data,callback){
- let table = `<table style="line-height:3;">`;
- for (let item of data) {
- table += `<tr>`;
- for (let i of item) {
- let width = i.width || '70px';
- let height = i.height || '25px';
- let color = i.color || 'balck';
- let fontSize = i.fontSize || '16px';
- let textAlign = i.textAlign || 'left';
- let border = i.border || 'none';
- let colspan = i.colspan || 1;
- let rowspan = i.rowspan || 1;
- if(i.type==='img'){
- let imgWidth = i.imgWidth || 25;
- let imgHeight = i.imgHeight || 25;
- let src = await saveImg(name,i.content);
- console.log(src);
- if(src === 'fail'){
- uni.hideLoading();
- uni.showToast({
- title: '导出失败,请确认是否授权文件权限',
- icon: 'none'
- });
- return;
- }
- 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>`;
- imgCount ++;
- }else{
- 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>`;
- }
- }
- table += `</tr>`;
- }
- table += `</table>`;
- exportFile(formatTemplate(table),name,callback);
- }
-
- function formatTemplate(data) {
- 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>sheet1</x:Name>
- <x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet>
- </x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]-->
- </head><body>${data}</body></html>`;
- return template;
- }
-
- function exportFile(fileData,documentName,callback) {
- createDir(documentName,(dirEntry,path,name) => {
- dirEntry.getFile(`${documentName}.xlsx`, {
- create: true
- }, (fileEntry) => {
- fileEntry.createWriter((writer) => {
- writer.onwritestart = (e) => {
- console.log('onwritestart');
- }
- writer.onwrite = (e) => {
- // 成功导出数据;
- setTimeout(() => {
- uni.hideLoading();
- uni.showToast({
- title: "成功导出",
- icon: "success"
- });
- console.log(`导出成功,文件位置:${path}/${documentName}.xlsx`);
- callback(`${path}/${documentName}.xlsx`);
- }, 1000);
- };
- // 写入内容;
- writer.write(fileData);
- }, function(e) {
- console.log(e.message);
- uni.hideLoading();
- uni.showToast({
- title: '导出失败,请确认是否授权文件权限',
- icon: 'none'
- });
- });
- },err=>{
- console.log(err);
- uni.hideLoading();
- uni.showToast({
- title: '导出失败,请确认是否授权文件权限',
- icon: 'none'
- });
- });
- });
- }
-
- function saveImg(name,base64){
- return new Promise((resolve,reject) => {
- createDir(name,(dirEntry,path,name) => {
- let bitmap = new plus.nativeObj.Bitmap('图片'+imgCount);
- bitmap.loadBase64Data(base64,res => {
- console.log(`图片${imgCount}加载base64成功`);
- let fileName = '_documents/导出的Excel/' + name + '/图片' + imgCount + '.jpg';
- bitmap.save(fileName,{overwrite:true,quality:100,format:'jpg'},res1 => {
- console.log(res1);
- console.log(`图片${imgCount}保存成功,路径:${fileName}`);
- bitmap.clear();
- resolve('success');
- },err1 => {
- console.log(err1);
- reject('fail');
- });
- },err => {
- console.log(err);
- reject('fail');
- });
- });
- });
- }
-
- function createDir(name,callback){
- plus.io.requestFileSystem(plus.io.PUBLIC_DOCUMENTS, (fs) => {
- let rootObj = fs.root;
- let fullPath = rootObj.fullPath;
- rootObj.getDirectory('导出的Excel',{create:true},dirEntry => {
- dirEntry.getDirectory(name,{create:true},dirEntry2 => {
- let pathStr = fullPath.replace("/storage/emulated/0", "");
- pathStr += '导出的Excel/'+name;
- console.log(`目录${pathStr}创建成功`);
- callback(dirEntry2,pathStr,name);
- },err2=>{
- console.log(err2);
- uni.hideLoading();
- uni.showToast({
- title: '导出失败,请确认是否授权文件权限',
- icon: 'none'
- });
- });
- },err1=>{
- console.log(err1);
- uni.hideLoading();
- uni.showToast({
- title: '导出失败,请确认是否授权文件权限',
- icon: 'none'
- });
- });
- },err=>{
- console.log(err);
- uni.hideLoading();
- uni.showToast({
- title: '导出失败,请确认是否授权文件权限',
- icon: 'none'
- });
- });
- }
-
- module.exports = doExport;
二、组件中使用
- let doExport = require('@/common/exportExcel.js')
- import { jsons } from './excelJson.js'
-
- async printingOutline(item) { // 离线导出
- //要导出的json数据
- const jsonData = JSON.parse(JSON.stringify(jsons))
- const that = this
- doExport('input', jsonData, function(result){
- that.open(result)
- })
- },
-
- open(url) { // 打开excel
- uni.openDocument({
- filePath: '/storage/emulated/0'+url, // 要加上前面/storage/emulated/0,不然打不开
- success:(res3) =>console.log('成功打开文档'),
- fail: (err) => {
- console.log('失败')
- console.log(err)
- }
- })
- }
excelJson.js
- export const jsons = [
- [
- {
- content: '预防控制中心',
- type: 'text',
- fontSize: '18px',
- colspan: 18,
- textAlign: 'center',
- height: '50px'
- }
- ],
- [
- {
- content: '采(抽)样登记表',
- type: 'text',
- fontSize: '18px',
- colspan: 18,
- textAlign: 'center',
- height: '50px'
- }
- ],
- [
- {
- id: 'test_category',
- content: '检验检测类别',
- type: 'text',
- fontSize: '10px',
- colspan: 18,
- border: 'solid 1px #000'
- }
- ],
- [
- {
- id: 'index',
- content: '序号',
- type: 'text',
- fontSize: '10px',
- border: 'solid 1px #000'
- },
- {
- id: 'sample_category_text',
- content: '样品类别',
- type: 'text',
- fontSize: '10px',
- border: 'solid 1px #000'
- },
- {
- id: 'sample_number',
- content: '样品编号',
- type: 'text',
- fontSize: '10px',
- border: 'solid 1px #000'
- },
- {
- id: 'sample_name',
- content: '样品名称',
- type: 'text',
- fontSize: '10px',
- },
- {
- id: 'sample_specifications_text',
- content: '样品规格',
- type: 'text',
- fontSize: '10px',
- },
- {
- id: 'quantity',
- content: '数量',
- type: 'text',
- fontSize: '10px',
- },
- {
- id: 'packaging_type_text',
- content: '包装类型',
- type: 'text',
- fontSize: '10px'
- },
- {
- id: 'sample_trademark',
- content: '样品商标',
- type: 'text',
- fontSize: '10px'
- },
- {
- id: 'packaging_form',
- content: '包装形式',
- type: 'text',
- fontSize: '10px'
- },
- {
- id: 'place_of_origin',
- content: '产地',
- type: 'text',
- fontSize: '10px',
- },
- {
- id: 'manufacturer',
- content: '生产厂家(样品来源)',
- type: 'text',
- fontSize: '10px',
- },
- {
- id: 'manufacturer_address',
- content: '生产厂家地址',
- type: 'text',
- fontSize: '10px',
- },
- {
- id: 'manufacture_date_number',
- content: '生产日期/批号',
- type: 'text',
- fontSize: '10px',
- },
- {
- id: 'sample_character_text',
- content: '样品性状',
- type: 'text',
- fontSize: '10px',
- },
- {
- id: 'storage_condition_text',
- content: '保存条件',
- type: 'text',
- fontSize: '10px',
- },
- {
- id: 'sample_locations',
- content: '采样地点',
- type: 'text',
- fontSize: '10px',
- },
- {
- id: 'sample_locations_type_text',
- content: '采样地点类型',
- type: 'text',
- fontSize: '10px',
- },
- {
- id: 'remark',
- content: '备注',
- type: 'text',
- fontSize: '10px',
- }
- ]
- ]
三、导出结果
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。