Firebase 如何在Flatter中创建从Firestore到CSV文件的数据表

Firebase 如何在Flatter中创建从Firestore到CSV文件的数据表,firebase,csv,flutter,pdf,google-cloud-firestore,Firebase,Csv,Flutter,Pdf,Google Cloud Firestore,好的,故事是这样的: import 'dart:io'; import 'package:basic_utils/basic_utils.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:csv/csv.dart'; import 'package:flutter/material.dart'; import 'package:path_provider/path_provider.d

好的,故事是这样的:

  import 'dart:io';

import 'package:basic_utils/basic_utils.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:csv/csv.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_email_sender/flutter_email_sender.dart';

class AdminPage extends StatefulWidget {
  static final TextEditingController _emailController = TextEditingController();

  @override
  _AdminPageState createState() => _AdminPageState();
}

class _AdminPageState extends State<AdminPage> {
  final GlobalKey<FormState> _formkey = GlobalKey<FormState>();
  DocumentSnapshot _currentDocument;

  String filePath;
  String currentProcess;
  bool isProcessing = false;

  Future<String> get _localPath async {
    final directory = await getApplicationSupportDirectory();

    return directory.absolute.path;
  }

  Future<File> get _localFile async {
    final path = await _localPath;
    filePath = '$path/clouddata.csv';
    return File('$path/clouddata.csv').create();
  }



  List<List<dynamic>> rows = List<List<dynamic>>();
  getCsv(DocumentSnapshot document) async {
    setState(() {
      currentProcess = "Getting data from the cloud";
      isProcessing = true;
    });
    Firestore.instance
          .collection('Airline_Transactions').document(_currentDocument.documentID)
          .snapshots();
   {
      setState(() {
        currentProcess = "Decoding data";
      });
    }
    rows.add([
      "Date",
      "Airline",
      "Flight Number",
      "Terminal",
      "pax",
      "Infant",
      "Transit",
    ]);
    if (document.data != null) {
      for (int i = 0; i < document.data.length; i++) {
        List<dynamic> row = List<dynamic>();
        row.add(document.data[i]["date"].toString());
        row.add(document.data[i]["airline"].toString());
        row.add(document.data[i]["flight_number"].toString());
        row.add(document.data[i]["terminal"].toString());
        row.add(document.data[i]["pax"].toString());
        row.add(document.data[i]["infant"].toString());
        row.add(document.data[i]["transit"].toString());
        rows.add(row);
      }


      File f = await _localFile.whenComplete(() {
        setState(() {
          currentProcess = "Writing to CSV";
        });
      });
      String csv = const ListToCsvConverter().convert(rows);
      f.writeAsString(csv);
       filePath = f.uri.path;
    }
  }

  sendMailAndAttachment() async {
    final Email email = Email(
      body:
      'Data Collected and Compiled by the Datum App. <br> A CSV file is attached to this <b>mail</b> <hr><br> Compiled at ${DateTime.now()}',
      subject: 'Datum Entry for ${DateTime.now().toString()}',
      recipients: [AdminPage._emailController.text],
      isHTML: true,
      attachmentPath: filePath,
    );

    await FlutterEmailSender.send(email);
  }

  GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(title: Text("Datum Dash")),
      body: ListView(
        padding: EdgeInsets.only(top: 45, right: 10, left: 10, bottom: 20),
        children: <Widget>[
          Text("Welcome to DashBoard",
              style: TextStyle(fontSize: 30, fontWeight: FontWeight.w500)),
          Form(
            key: _formkey,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.only(top: 20.0),
                  child: TextFormField(
                    controller: AdminPage._emailController,
                    validator: (str) => (str.length == 0)
                        ? "please enter your email"
                        : (!EmailUtils.isEmail(str))
                        ? "please enter a valid email"
                        : null,
                    decoration: InputDecoration(
                        labelText: "Enter your email",
                        border: OutlineInputBorder(),
                        suffixIcon: Icon(Icons.email)),
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.only(top: 8.0),
                  child: RaisedButton(
                    color: Theme.of(context).accentColor,
                    child: Text("Compile and Send"),
                    onPressed: (isProcessing)
                        ? null
                        : () async {
                      if (_formkey.currentState.validate()) {
                        try {
                          final result =
                          await InternetAddress.lookup('google.com');
                          if (result.isNotEmpty &&
                              result[0].rawAddress.isNotEmpty) {
                            await getCsv(_currentDocument).then((v) {
                              setState(() {
                                currentProcess =
                                "Compiling and sending mail";
                              });
                              sendMailAndAttachment().whenComplete(() {
                                setState(() {
                                  isProcessing = false;
                                });
                                _scaffoldKey.currentState
                                    .showSnackBar(SnackBar(
                                  content: Text("Data Sent"),
                                ));
                              });
                            });
                          }
                        } on SocketException catch (_) {
                          _scaffoldKey.currentState.showSnackBar(SnackBar(
                            content: Text(
                                "Connect your device to the internet, and try again"),
                          ));
                        }
                      }
                    },
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Visibility(
                    visible: (isProcessing) ? true : false,
                    child: Row(
                      children: <Widget>[
                        SizedBox(
                            child: CircularProgressIndicator(),
                            height: 25,
                            width: 25),
                        Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Text("$currentProcess"),
                        )
                      ],
                    ),
                  ),
                ),
              ],
            ),
          )
        ],
      ),
    );
  }
}
我的应用程序可以创建报告,现在这些报告整齐地显示在表格中。数据正在从firestore流式传输

问题:

  import 'dart:io';

import 'package:basic_utils/basic_utils.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:csv/csv.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_email_sender/flutter_email_sender.dart';

class AdminPage extends StatefulWidget {
  static final TextEditingController _emailController = TextEditingController();

  @override
  _AdminPageState createState() => _AdminPageState();
}

class _AdminPageState extends State<AdminPage> {
  final GlobalKey<FormState> _formkey = GlobalKey<FormState>();
  DocumentSnapshot _currentDocument;

  String filePath;
  String currentProcess;
  bool isProcessing = false;

  Future<String> get _localPath async {
    final directory = await getApplicationSupportDirectory();

    return directory.absolute.path;
  }

  Future<File> get _localFile async {
    final path = await _localPath;
    filePath = '$path/clouddata.csv';
    return File('$path/clouddata.csv').create();
  }



  List<List<dynamic>> rows = List<List<dynamic>>();
  getCsv(DocumentSnapshot document) async {
    setState(() {
      currentProcess = "Getting data from the cloud";
      isProcessing = true;
    });
    Firestore.instance
          .collection('Airline_Transactions').document(_currentDocument.documentID)
          .snapshots();
   {
      setState(() {
        currentProcess = "Decoding data";
      });
    }
    rows.add([
      "Date",
      "Airline",
      "Flight Number",
      "Terminal",
      "pax",
      "Infant",
      "Transit",
    ]);
    if (document.data != null) {
      for (int i = 0; i < document.data.length; i++) {
        List<dynamic> row = List<dynamic>();
        row.add(document.data[i]["date"].toString());
        row.add(document.data[i]["airline"].toString());
        row.add(document.data[i]["flight_number"].toString());
        row.add(document.data[i]["terminal"].toString());
        row.add(document.data[i]["pax"].toString());
        row.add(document.data[i]["infant"].toString());
        row.add(document.data[i]["transit"].toString());
        rows.add(row);
      }


      File f = await _localFile.whenComplete(() {
        setState(() {
          currentProcess = "Writing to CSV";
        });
      });
      String csv = const ListToCsvConverter().convert(rows);
      f.writeAsString(csv);
       filePath = f.uri.path;
    }
  }

  sendMailAndAttachment() async {
    final Email email = Email(
      body:
      'Data Collected and Compiled by the Datum App. <br> A CSV file is attached to this <b>mail</b> <hr><br> Compiled at ${DateTime.now()}',
      subject: 'Datum Entry for ${DateTime.now().toString()}',
      recipients: [AdminPage._emailController.text],
      isHTML: true,
      attachmentPath: filePath,
    );

    await FlutterEmailSender.send(email);
  }

  GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(title: Text("Datum Dash")),
      body: ListView(
        padding: EdgeInsets.only(top: 45, right: 10, left: 10, bottom: 20),
        children: <Widget>[
          Text("Welcome to DashBoard",
              style: TextStyle(fontSize: 30, fontWeight: FontWeight.w500)),
          Form(
            key: _formkey,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.only(top: 20.0),
                  child: TextFormField(
                    controller: AdminPage._emailController,
                    validator: (str) => (str.length == 0)
                        ? "please enter your email"
                        : (!EmailUtils.isEmail(str))
                        ? "please enter a valid email"
                        : null,
                    decoration: InputDecoration(
                        labelText: "Enter your email",
                        border: OutlineInputBorder(),
                        suffixIcon: Icon(Icons.email)),
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.only(top: 8.0),
                  child: RaisedButton(
                    color: Theme.of(context).accentColor,
                    child: Text("Compile and Send"),
                    onPressed: (isProcessing)
                        ? null
                        : () async {
                      if (_formkey.currentState.validate()) {
                        try {
                          final result =
                          await InternetAddress.lookup('google.com');
                          if (result.isNotEmpty &&
                              result[0].rawAddress.isNotEmpty) {
                            await getCsv(_currentDocument).then((v) {
                              setState(() {
                                currentProcess =
                                "Compiling and sending mail";
                              });
                              sendMailAndAttachment().whenComplete(() {
                                setState(() {
                                  isProcessing = false;
                                });
                                _scaffoldKey.currentState
                                    .showSnackBar(SnackBar(
                                  content: Text("Data Sent"),
                                ));
                              });
                            });
                          }
                        } on SocketException catch (_) {
                          _scaffoldKey.currentState.showSnackBar(SnackBar(
                            content: Text(
                                "Connect your device to the internet, and try again"),
                          ));
                        }
                      }
                    },
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Visibility(
                    visible: (isProcessing) ? true : false,
                    child: Row(
                      children: <Widget>[
                        SizedBox(
                            child: CircularProgressIndicator(),
                            height: 25,
                            width: 25),
                        Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Text("$currentProcess"),
                        )
                      ],
                    ),
                  ),
                ),
              ],
            ),
          )
        ],
      ),
    );
  }
}
有一个必备功能,可以将报告从应用程序中导出,比如发送电子邮件。所以我尝试将其导出为PDF,但它只保存当前在scaffold中查看的内容,这意味着需要滚动才能显示/查看的行和列不会导出为PDF。目前,我正试图对包含firestore实例的所有数据流的CSV文件执行相同的操作,在数据表视图中对其进行格式化

**用完整的代码编辑** 下面是代码:

  import 'dart:io';

import 'package:basic_utils/basic_utils.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:csv/csv.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_email_sender/flutter_email_sender.dart';

class AdminPage extends StatefulWidget {
  static final TextEditingController _emailController = TextEditingController();

  @override
  _AdminPageState createState() => _AdminPageState();
}

class _AdminPageState extends State<AdminPage> {
  final GlobalKey<FormState> _formkey = GlobalKey<FormState>();
  DocumentSnapshot _currentDocument;

  String filePath;
  String currentProcess;
  bool isProcessing = false;

  Future<String> get _localPath async {
    final directory = await getApplicationSupportDirectory();

    return directory.absolute.path;
  }

  Future<File> get _localFile async {
    final path = await _localPath;
    filePath = '$path/clouddata.csv';
    return File('$path/clouddata.csv').create();
  }



  List<List<dynamic>> rows = List<List<dynamic>>();
  getCsv(DocumentSnapshot document) async {
    setState(() {
      currentProcess = "Getting data from the cloud";
      isProcessing = true;
    });
    Firestore.instance
          .collection('Airline_Transactions').document(_currentDocument.documentID)
          .snapshots();
   {
      setState(() {
        currentProcess = "Decoding data";
      });
    }
    rows.add([
      "Date",
      "Airline",
      "Flight Number",
      "Terminal",
      "pax",
      "Infant",
      "Transit",
    ]);
    if (document.data != null) {
      for (int i = 0; i < document.data.length; i++) {
        List<dynamic> row = List<dynamic>();
        row.add(document.data[i]["date"].toString());
        row.add(document.data[i]["airline"].toString());
        row.add(document.data[i]["flight_number"].toString());
        row.add(document.data[i]["terminal"].toString());
        row.add(document.data[i]["pax"].toString());
        row.add(document.data[i]["infant"].toString());
        row.add(document.data[i]["transit"].toString());
        rows.add(row);
      }


      File f = await _localFile.whenComplete(() {
        setState(() {
          currentProcess = "Writing to CSV";
        });
      });
      String csv = const ListToCsvConverter().convert(rows);
      f.writeAsString(csv);
       filePath = f.uri.path;
    }
  }

  sendMailAndAttachment() async {
    final Email email = Email(
      body:
      'Data Collected and Compiled by the Datum App. <br> A CSV file is attached to this <b>mail</b> <hr><br> Compiled at ${DateTime.now()}',
      subject: 'Datum Entry for ${DateTime.now().toString()}',
      recipients: [AdminPage._emailController.text],
      isHTML: true,
      attachmentPath: filePath,
    );

    await FlutterEmailSender.send(email);
  }

  GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(title: Text("Datum Dash")),
      body: ListView(
        padding: EdgeInsets.only(top: 45, right: 10, left: 10, bottom: 20),
        children: <Widget>[
          Text("Welcome to DashBoard",
              style: TextStyle(fontSize: 30, fontWeight: FontWeight.w500)),
          Form(
            key: _formkey,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.only(top: 20.0),
                  child: TextFormField(
                    controller: AdminPage._emailController,
                    validator: (str) => (str.length == 0)
                        ? "please enter your email"
                        : (!EmailUtils.isEmail(str))
                        ? "please enter a valid email"
                        : null,
                    decoration: InputDecoration(
                        labelText: "Enter your email",
                        border: OutlineInputBorder(),
                        suffixIcon: Icon(Icons.email)),
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.only(top: 8.0),
                  child: RaisedButton(
                    color: Theme.of(context).accentColor,
                    child: Text("Compile and Send"),
                    onPressed: (isProcessing)
                        ? null
                        : () async {
                      if (_formkey.currentState.validate()) {
                        try {
                          final result =
                          await InternetAddress.lookup('google.com');
                          if (result.isNotEmpty &&
                              result[0].rawAddress.isNotEmpty) {
                            await getCsv(_currentDocument).then((v) {
                              setState(() {
                                currentProcess =
                                "Compiling and sending mail";
                              });
                              sendMailAndAttachment().whenComplete(() {
                                setState(() {
                                  isProcessing = false;
                                });
                                _scaffoldKey.currentState
                                    .showSnackBar(SnackBar(
                                  content: Text("Data Sent"),
                                ));
                              });
                            });
                          }
                        } on SocketException catch (_) {
                          _scaffoldKey.currentState.showSnackBar(SnackBar(
                            content: Text(
                                "Connect your device to the internet, and try again"),
                          ));
                        }
                      }
                    },
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Visibility(
                    visible: (isProcessing) ? true : false,
                    child: Row(
                      children: <Widget>[
                        SizedBox(
                            child: CircularProgressIndicator(),
                            height: 25,
                            width: 25),
                        Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Text("$currentProcess"),
                        )
                      ],
                    ),
                  ),
                ),
              ],
            ),
          )
        ],
      ),
    );
  }
}
导入'dart:io';
导入“包:basic_utils/basic_utils.dart”;
导入“包:cloud_firestore/cloud_firestore.dart”;
导入“包:csv/csv.dart”;
进口“包装:颤振/材料.省道”;
导入“package:path_provider/path_provider.dart”;
导入“package:flatter_email_sender/flatter_email_sender.dart”;
类AdminPage扩展了StatefulWidget{
静态最终TextEditingController _emailController=TextEditingController();
@凌驾
_AdminPageState createState()=>\u AdminPageState();
}
类_AdminPageState扩展了状态{
最终的GlobalKey _formkey=GlobalKey();
文档快照_currentDocument;
字符串文件路径;
字符串处理;
bool isProcessing=false;
未来获取\u本地路径异步{
最终目录=等待getApplicationSupportDirectory();
返回directory.absolute.path;
}
未来获取\u本地文件异步{
最终路径=等待_localPath;
filePath='$path/clouddata.csv';
返回文件(“$path/clouddata.csv”).create();
}
列表行=列表();
getCsv(文档快照文档)异步{
设置状态(){
currentProcess=“从云获取数据”;
isProcessing=true;
});
Firestore.instance
.collection(“航空公司交易”).document(\u currentDocument.documentID)
.快照();
{
设置状态(){
currentProcess=“解码数据”;
});
}
行。添加([
“日期”,
“航空公司”,
“航班号”,
“终端”,
“和平”,
“婴儿”,
“过境”,
]);
if(document.data!=null){
for(int i=0;i此邮件附有一个CSV文件。

在${DateTime.now()}编译, 主题:${DateTime.now().toString()}的数据项, 收件人:[AdminPage.\u emailController.text], 伊什特尔:没错, attachmentPath:filePath, ); 等待电子邮件发件人。发送(电子邮件); } GlobalKey _scaffoldKey=GlobalKey(); @凌驾 小部件构建(构建上下文){ 返回脚手架( 钥匙:_scaffoldKey, appBar:appBar(标题:文本(“基准线”)), 正文:ListView( 填充:仅限边集(顶部:45,右侧:10,左侧:10,底部:20), 儿童:[ 文本(“欢迎使用仪表板”, 样式:TextStyle(fontSize:30,fontWeight:fontWeight.w500)), 形式( 键:_formkey, 子:列( crossAxisAlignment:crossAxisAlignment.start, 儿童:[ 填充物( 填充:仅限常量边集(顶部:20.0), 子项:TextFormField( 控制器:AdminPage.\u emailController, 验证程序:(str)=>(str.length==0) ?“请输入您的电子邮件” :(!EmailUtils.isEmail(str)) ?“请输入有效的电子邮件” :null, 装饰:输入装饰( labelText:“输入您的电子邮件”, 边框:OutlineInputBorder(), 后缀:图标(Icons.email)), ), ), 填充物( 填充:仅限常量边集(顶部:8.0), 孩子:升起按钮( 颜色:主题。背景。强调颜色, 子项:文本(“编译并发送”), onPressed:(正在处理) 无效的 :()异步{ if(_formkey.currentState.validate()){ 试一试{ 最终结果= 等待InternetAddress.lookup('google.com'); 如果(result.isNotEmpty)&& 结果[0].rawAddress.isNotEmpty){ 等待getCsv(_currentDocument)。然后((v){ 设置状态(){ 当前进程= “编写和发送邮件”; }); sendMailAndAttachment()。完成时(){ 设置状态(){ isProcessing=false; }); _sc