uniapp打包App实现导出xlsx

1,789 阅读2分钟

前言

在日常开发中难免遇到,处理数据量比较大时,或者是针对table表格数据,想后续查看,编辑,备份操作时,通常需要导入为xlsx文件,pc端可以通过xlsx的npm包进行导出,但是App想实现导出xlsx又应该如何操作呢?

1. 获取写文件操作对象✍️

这里摒弃大部分情况下后端返回Blob的数据流格式,想想如何把一个普通的数组对象转换成表结构,导出xlsx呢?

这里介绍一下HTML5+API Reference的IO模块管理本地文件系统。

// 请求手机本地文件系统对象
void plus.io.requestFileSystem( type, succesCB, errorCB );

具体代码

// 第一个参数为本地文件系统常量
// 第二个参数为成功的回调
plus.io.requestFileSystem(plus.io.PUBLIC_DOWNLOADS,(fs) => {
   // 拿到fs模块进行文件操作
   fs.root!.getFile(`订单.xlsx`, { create: true }, (fileEntry) => {
        fileEntry.createWriter((writer) => {
          writer.write();
          // 写入文件是否成功
          writer.onwrite = (e: any) => {
            // 写入成功的回调
          }
        }
 })

拿到fs模块可进行文件操作,找到root(文件系统的根目录),然后调用getFile()函数创建或打开文件,{ create: true },代表

在本地打开一个 订单.xlsx的文件的文件,有就打开,没有就在本地创建。然后获取文件关联的写文件操作对象FileWriter,注: writer.write();只能传入字符串。

2. 生成HTML字符串👊

以上 writer.write();可以写入HTML字符串,我们只需把想要展示的数据转成HTML字符串即可。

附上代码:

// 可通过行内样式,调整布局
// 请求后端接口获取数据比如[{name:'刘德华',age:20},{name:'张学友',age:30}]
let newHtmlStr = `
  <html>
  <head>
  </head>
  <body>
      <table border="1">
        <tr style="height:50px;font-size:16px;font-weight:bold;font-family: 微软雅黑;">
          <td style="background-color: skyblue;">收货日期</td>
          <td style="background-color: skyblue;">收货时间</td>
          <td style="background-color: skyblue;">ID</td>
          <td style="background-color: skyblue;">团队名</td>
          <td style="background-color: skyblue;">商品分类</td>
          <td style="background-color: skyblue;">商品规格</td>
          <td style="background-color: skyblue;">商品名</td>
          <td style="background-color: skyblue;">采购数量</td>
          <td style="background-color: skyblue;">采购单位</td>
          <td style="background-color: skyblue;">采购方备注</td>
          <td style="background-color: skyblue;">适配配注</td>
          <td style="background-color: skyblue;">订单状态</td>
        </tr>
       ${downList
              .map((item) => {
                return `
                  <tr style="font-family: 微软雅黑;">
                    <td>${item.orderTime}</td>
                    <td>${item.receiveTime}</td>
                    <td>${item.bgroupId}</td>
                    <td>${item.groupName}</td>
                    <td>${item.categoryName}</td>
                    <td>${item.categoryAncestor}</td>
                    <td>${item.goodName}</td>
                    <td>${item.amount}</td>
                    <td>${item.unitWeighName}</td>
                    <td>${item.remark}</td>
                    <td>${item.allowContent}</td>
                    <td>${orderStatus(item.orderStatus)}</td>
                  </tr>
                `;
              })
              .join("")}
      </table>
  </body>

  </html>
            `;

3. 分享文件👇

3.1. 使用插件

最后通过uniapp插件市场的《安卓ios分享任意类型文件》实现唤起系统分享面板

插件地址

// 导入插件
const FileShare = uni.requireNativePlugin("life-FileShare");
// 使用插件自动唤起系统分享面板
FileShare.render(
  {
    type: "SYSTEM", //QQ为QQ,微信为WX,系统默认是SYSTEM,不填写默认SYSTEM
    filePath: plus.io.convertLocalFileSystemURL(
      `file://${e.target.fileName}`
    ),
  },
  (result: any) => {
    console.log(result);
  },
  (err: any) => {
    console.log(err);
  }
);

完整代码附上:

 plus.io.requestFileSystem(
    plus.io.PUBLIC_DOWNLOADS,
    (fs) => {
      fs.root!.getFile(`订单.xlxs`, { create: true }, (fileEntry) => {
        fileEntry.createWriter((writer) => {
          let newHtmlStr = `
  <html>
  <head>
  </head>
  <body>
      <table border="1">
        <tr style="height:50px;font-size:16px;font-weight:bold;font-family: 微软雅黑;">
          <td style="background-color: skyblue;">收货日期</td>
          <td style="background-color: skyblue;">收货时间</td>
          <td style="background-color: skyblue;">ID</td>
          <td style="background-color: skyblue;">团队名</td>
          <td style="background-color: skyblue;">商品分类</td>
          <td style="background-color: skyblue;">商品规格</td>
          <td style="background-color: skyblue;">商品名</td>
          <td style="background-color: skyblue;">采购数量</td>
          <td style="background-color: skyblue;">采购单位</td>
          <td style="background-color: skyblue;">采购方备注</td>
          <td style="background-color: skyblue;">适配配注</td>
          <td style="background-color: skyblue;">订单状态</td>
        </tr>
       ${downList
              .map((item) => {
                return `
                  <tr style="font-family: 微软雅黑;">
                    <td>${item.orderTime}</td>
                    <td>${item.receiveTime}</td>
                    <td>${item.bgroupId}</td>
                    <td>${item.groupName}</td>
                    <td>${item.categoryName}</td>
                    <td>${item.categoryAncestor}</td>
                    <td>${item.goodName}</td>
                    <td>${item.amount}</td>
                    <td>${item.unitWeighName}</td>
                    <td>${item.remark}</td>
                    <td>${item.allowContent}</td>
                    <td>${orderStatus(item.orderStatus)}</td>
                  </tr>
                `;
              })
              .join("")}
      </table>
  </body>

  </html>
            `;
          writer.write(newHtmlStr);
          // 写入文件是否成功
          writer.onwrite = (e: any) => {
            FileShare.render(
              {
                type: "SYSTEM", //QQ为QQ,微信为WX,系统默认是SYSTEM,不填写默认SYSTEM
                filePath: plus.io.convertLocalFileSystemURL(
                  `file://${e.target.fileName}`
                ),
              },
              (result: any) => {
                console.log(result);
              },
              (err: any) => {
                console.log(err);
              }
            );
          };
        });
      });
    },
    (err) => {
      Toast("none", "文件系统访问失败");
    }
  );

3.2. 效果展示

以华为手机为例:

导出后的结果:

image.png

3.3. 注意点

针对一些人电脑上的wps或office版本比较低

// 可采用.xls以后缀名结尾
fs.root!.getFile(`订单.xls`, { create: true }, (fileEntry) => {})

以下是常见后缀名,供参考:

写在最后

本方案未必最优,可能还有其他方案,以文档为主,如有问题欢迎指出,本文章主要阐述开发中可能会遇到的需求,以及我个人的一些解决办法。希望对大家有一定的班助。😀😀😀😀😀