0
点赞
收藏
分享

微信扫一扫

flutter导出文本、图片到excel

蓝莲听雨 2022-03-24 阅读 84

前言

最近做flutter项目有个需求是将数据导出excel表格,原本需求是图片以链接的形式导出,直接去pubdev上搜官方的excel插件就能实现,后来需求变成导出的图片要在excel文件中直接显示出来,官方的excel插件只支持写入文本,去pubdev上看到了别的插件syncfusion_flutter_xlsio

里面有插入图片的api

 这里插入的是本地图片,既然它可以实现插入图片,那么接下来要解决如何把网络图片插入进去

// 插件中的这段代码是写入图片的关键
// 先是拿到图片的文件流Uint8List格式
final List<int> bytes = File('image.png').readAsBytesSync();
// 将文件流写入
final Picture picture = sheet.picutes.addStream(1, 1, bytes);

那么要考虑如何将在线图片地址转成Uint8List格式,先在项目中引入需要的库

import 'dart:io';
import 'package:image/image.dart' as imgLib;
import 'package:dio/dio.dart';
import 'dart:convert';
import 'package:syncfusion_flutter_xlsio/xlsio.dart' as Flutter_xlsio;
import 'package:path_provider/path_provider.dart' as path_provider;

这里封装一个同步的方法拿到图片的文件流

// url为网络图片地址
Future netImageToBase64(url) async {
        var response = await Dio()
        .get(url, options: Options(responseType: ResponseType.bytes));
    print(
        "Uint8List.fromList(response.data)===${Uint8List.fromList(response.data)}");
    // 以这种方式拿到了Uint8List格式的图片数据流,接下来可以为所欲为了
    // 这里是压缩图片的操作,如果不压缩的话图片会很大占用Excel很多行和列
    // 先转成Image格式,使用Image的Api调整图片然后再转回Uint8List格式
    imgLib.Image image = imgLib.decodeImage(Uint8List.fromList(response.data));
    //拷贝图像并调整大小(保持图片长宽比例不变).thumbnail是调整时候的图片这时是Image类型
    imgLib.Image thumbnail = imgLib.copyResize(image, height: 120);
    将图片解码成Uint8List
    final List<int> bytesTmp = imgLib.encodePng(thumbnail);
    return bytesTmp;
}

调用示例注意下面代码中的dataList是我用来接收数据的List类型的变量,代码里没有显示定义

Future<void> generateExcel() async {
    // 创建一个Excel文档.
    final Flutter_xlsio.Workbook workbook = new Flutter_xlsio.Workbook();
    //通过索引访问工作表第0个sheet.
    final Flutter_xlsio.Worksheet sheet = workbook.worksheets[0];
    sheet.getRangeByName('A1').columnWidth = 20.00;
    sheet.getRangeByName('A2').rowHeight = 100.00;
    sheet.getRangeByName('B1').columnWidth = 13.82;
    sheet.getRangeByName('C1').columnWidth = 20.00;
    sheet.getRangeByName('D1').columnWidth = 13.82;
    sheet.getRangeByName('E1').columnWidth = 50.00;
    // 垂直方向文字
    sheet.getRangeByName('A2').cellStyle.vAlign = Flutter_xlsio.VAlignType.top;
    // 设置标题
    sheet.getRangeByName('A1').setText('任务编号');
    sheet.getRangeByName('B1').setText('提交人id');
    sheet.getRangeByName('C1').setText('提交时间');
    sheet.getRangeByName('D1').setText('任务状态');
    sheet.getRangeByName('E1').setText('验证图片');
    // 这里循环取数据
    for (int i = 0; i < dataList.length; i++) {
      sheet.getRangeByIndex(i + 2, 1).setText(dataList[i]['tid'].toString());
      sheet
          .getRangeByIndex(i + 2, 2)
          .setText(dataList[i]['uid'].toString());
      sheet
          .getRangeByIndex(i + 2, 3)
          .setText(dataList[i]['create_time'].toString());
      sheet
          .getRangeByIndex(i + 2, 4)
          .setText(dataList[i]['taskstatus'].toString());
      // 开始存图
      Uint8List imageBytes =
          await netImageToBase64(dataList[i]['imgurl1']);
      sheet.pictures.addStream(i + 2, 5, imageBytes);
    }
    List<int> bytes = workbook.saveAsStream();
    workbook.dispose();
    final Directory directory =
        await path_provider.getApplicationDocumentsDirectory();
    final String path = directory.path;
    final File file = File('$path/output.xlsx');
    file.writeAsBytes(bytes);
    // 触发分享
    Share.shareFiles(["$path/output.xlsx"], text: 'Great picture');
}

写如图片的重要代码就是循环体里的这部分

Uint8List imageBytes =
          await netImageToBase64(dataList[i]['imgurl1']);

最后还可以配合一个插件触发安卓自带的分享,可以直接将文件分享到微信QQ等,版本可去pubdev自行获取,调用方式在上述示例代码中已详细列出

import 'package:share/share.dart';// 引入

// 调用
Share.shareFiles(["$path/output.xlsx"], text: 'Great picture');

写入之后的文件

总结

主要实现了将网络图片写入Excel文件,写入逻辑还没有优化,第一次写这种需求,据了解是服务端是可以做,在服务端生成后你直接拿到下载地址或者文件流都可以,但是没有办法,我迫不得已只能前端来写。有问题的话大家可以留言一起交流。

举报

相关推荐

0 条评论