• 微信小程序生成Excel


    微信小程序生成Excel

    一、问题描述

    最近一直在查找在微信小程序中生成Excel的办法。需求就是根据一个json数据或者对象数组,生成一个Excel文件,或者打开Excel文件。网上找了很久,没找到很有效的解决办法。最后自己动手做了一个,不过生成效率还比较低。

    二、实现思路

    我比较赞同的方法有两种,第一种是使用api来实现。如果你有个服务器,那么一切就好办了。只需要把数据传给服务器,然后服务器生成Excel文件,并返回文件的url。之后通过wx.downloadFile下载文件,配合wx.openDocument打开文件即可。至于如何编写一个返回Excel文件url的api,方法就太多了。

    但是不是所有人都有服务器,所以还得相关离线的办法生成Excel文件。我的思路是,Excel文件本身是一个压缩文件,我们只需要安装Excel的目录结构,逐个文件和文件夹创建,如何将文件压缩为xx.xlsx文件即可。

    结果查找,腾讯狗没有提供压缩相关的api。不过js倒是有现成jszip库可以使用,有了jszip,我们就可以开始实现了。

    三、具体实现

    先下载jszip库,然后将dist中的js文件放到小程序下的utils目录下。

    在pages/index/index.wxml中写个按钮:

    
    <view class="container">
      <view>
          <button bindtap="createXLSX_zip">生成压缩包button>
      view>
    view>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    然后在pages/index/index.js中最上面导入JSZip:

    const JSZip = require("../../utils/jszip");
    
    • 1

    并编写响应函数:

    createXLSX_zip() {
        const fs = wx.getFileSystemManager();
        let zip = new JSZip();
        const content = [
            {name: 'zack', age: 21, gender: 'male'},
            {name: 'alice', age: 20, gender: 'female'},
            {name: 'atom', age: 23, gender: 'male'},
            {name: 'rudy', age: 22, gender: 'male'},
        ]
        let contentXML = "";
        let idx = 0
        
        //按照Excel的规则,生成xml字符串
        let sheetData = ``
        let keys = Object.keys(content[0])
        for (let i = 0; i < keys.length; i++) {
            contentXML += `${keys[i]}`
            sheetData += `${String.fromCharCode(i + 'A'.charCodeAt())}1" t="s">${idx}`
            idx += 1
        }
        sheetData += ''
        for (let i = 0; i < content.length; i++) {
            sheetData += `${i + 2}" span="1:3">`
            for (let j = 0; j < keys.length; j++) {
                contentXML += `${content[i][keys[j]]}`
                sheetData += `${String.fromCharCode(j + 'A'.charCodeAt())}${j + 2}" t="s">${idx}`
                idx += 1
            }
            sheetData += ""
        }
        wx.showLoading({
            title: '正在生成',
        })
        zip.folder("docProps")
        zip.folder("xl")
        zip.folder("_rels")
        zip.file("[Content_Types].xml", '\n')
        zip.file(`docProps/app.xml`, '\nSheetJS工作表1Sheet1')
        zip.file(`docProps/core.xml`, '\nivx2022-07-11T07:23:00Z2022-07-11T07:25:43Z')
        zip.file(`docProps/custom.xml`, '\n784038AB04864B7497D2D5CF431A9FF02052-11.1.0.11830')
        zip.folder(`xl/theme`)
        zip.folder(`xl/worksheets`)
        zip.folder(`xl/_rels`)
        zip.file(`xl/sharedStrings.xml`, `\n${keys.length * (content.length + 1)}" uniqueCount="${keys.length * (content.length + 1)}">${contentXML}`)
        zip.file(`xl/styles.xml`, '\n')
        zip.file(`xl/workbook.xml`, '\n')
        zip.file(`xl/theme/theme1.xml`, '\n')
        zip.file(`xl/worksheets/sheet1.xml`, `\n${sheetData}`)
        zip.file(`xl/_rels/workbook.xml.rels`, '\n')
        zip.file(`_rels/.rels`, '\n')
        zip.generateAsync({type: "arraybuffer"})
            .then(function (content) {
            fs.writeFileSync(`${wx.env.USER_DATA_PATH}/result.xlsx`, content, 'utf-8');
            console.log(typeof (content));
            console.log(content);
            wx.hideLoading({
                success: (res) => {
                    wx.openDocument({
                        filePath: `${wx.env.USER_DATA_PATH}/result.xlsx`,
                        showMenu: true,
                        fileType: 'xlsx',
                        success: function (res) {
                            console.log('打开文档成功', res)
                        }
                    })
                },
            })
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    Excel的具体结构可以把后缀改成zip,然后解压查看。上面大多数文件都使用了默认的内容,只有xl/worksheets/sheet1.xml和xl/sharedStrings.xml两个文件进行了修改。其中sheet1.xml是表的具体数据,而sharedStrings.xml类似于一个词典,为了节约内存,单元格重复内容不会存储两次。不过这里我没有去考虑单元格重复的问题。

    使用上面的方法在Android和iOS都成功跑通了,不过速度不是很快。

    四、替代方法

    另外,这里提供一个替代方案。就是不生成Excel,转而生成csv文件。虽然不能完全替代Excel,但是也能有表格的效果。代码如下:

    const fs = wx.getFileSystemManager();
    wx.showLoading({
        title: '正在生成',
    })
    let dataStr = ""
    let keys = Object.keys(tableData[0])
    //标题
    for (let i = 0; i < keys.length; i++) {
        if (i != keys.length - 1) {
            dataStr += (keys[i] + ",")
        } else {
            dataStr += (keys[i] + "\n")
        }
    }
    //数据
    for (let i = 0; i < tableData.length; i++) {
        for (let j = 0; j < keys.length; j++) {
            if (j != keys.length - 1) {
                dataStr += (tableData[i][keys[j]] + ",")
            } else {
                dataStr += (tableData[i][keys[j]] + "\n")
            }
        }
    }
    wx.showLoading({
        title: '正在写入',
    })
    fs.writeFileSync(`${wx.env.USER_DATA_PATH}/data.csv`, dataStr, "utf-8")
    wx.hideLoading({
        success: (res) => {
            wx.showModal({
                title: '成功',
                content: '生成完成,是否分享',
                success(res) {
                    if (res.confirm) {
                        wx.shareFileMessage({
                            filePath: `${wx.env.USER_DATA_PATH}/data.csv`,
                            success() {
                            },
                            fail: console.error,
                        })
                    } else if (res.cancel) {
                    }
                }
            })
        },
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    不过wx.openDocument不支持csv文件,所以想到用其它应用打开。但是腾讯狗也没有提供其它程序打开的api,所以这里生成后分享文件。腾讯真狗!

  • 相关阅读:
    4个宝宝晚上不建议出门的原因,你知道吗?
    如何排查SQL慢查询?
    在线制作作息时间表
    前端工作总结195-一直报404
    Linux 进程管理
    Windows平台 使用jarsigner对Apk签名
    springMvc整合mybatis-plus
    C++ 太卷,转 Java?
    KOSMOS-2.5:密集文本的多模态读写模型
    EMQX Enterprise 5.5 发布:新增 Elasticsearch 数据集成
  • 原文地址:https://blog.csdn.net/ZackSock/article/details/125980913