Dmitry
 · 3d Artist

Custom Action: Save Firebase Document Collection as Excell and Upload to Firebase Cloud Storage

Hi all! I want to share with you a custom action.
 
We will save a collection of documents in Excell format and immediately send the file to the cloud storage. The file will be saved by any user to the shared cloud storage in a specific folder. The file will not be linked to any particular user.

Somewhere on the forum there was already a post on how to save the requested documents in excell format, but there were problems with the settings and the code did not work (I spent a couple of hours with it myself).

I modified the code a little based on that post and also the lessons
Dimitar Klaturov on YouTube

1. First you need to request a collection of documents using standard FlutterFlow tools and add a button (or something else) where you hang an action to generate Excell

2. Create a custom action and add dependencies, also dependencies on which dependencies depend








3. Add arguments, in my case these are four arguments (Call them in your own way):

      1) "Devices" is a required argument, it takes a collection of documents to save
      2) "FileNameE" - this will be the name of your Excell file when saving. Accepts a string from your application, such as a text field or App state.
     3-4) "TotalPrice and Waranty" - optional fields, in my case 1- takes the total amount of sales from the documents that we save in excell through the function and saves it in a separate line 2- counts how many documents there are with a certain field and writes it in a separate line
       You can add as many lines as 3 and 4 as you like and write new lines to the document

4. Add the return value, you will need it. Firebase after saving the document returns you a URL string with a link to the document. You can use this link, for example, in the next step to create a new document, for example, I have this "Reports for "DateTime", Place, Who sent". Or just use the open URL action and immediately download Excell to your device.
Also, in case of an error, return the string ERROR and you can add an error message, for example "Not sent, please try again"


5. Now let's look at the code, below there will be a screenshot with comments. !!!Important!!! Don't forget to change the names of my arguments to the names of yours in the code


IMPORTANT!!! You may not be able to write files to cloud storage due to CORS (usually this happens if you write or open files from other sites)
Solution here, change json file d google cloud

That's all, Below is the code itself, don't forget to change all the names to yours

import 'package:excel/excel.dart';
import 'dart:math' as math;
import 'dart:convert';
import 'dart:io';
import 'package:firebase_storage/firebase_storage.dart'; //Import all 5 dependencies

Future<String> saveDocumentsToExcel(
  List<DevicesRecord> devices,                // Arg 1
  String fileNameE,                           // Arg 2                  //Copy the code from here           and replace it with yours
  int totalPrice,                             // Arg 3
  int waranty,                                // Arg 4
) async {
  
  
  var excel = Excel.createExcel();


  Sheet sheetObject = excel['Your sheet name'];                                 //We write the name of your sheet inside the excell file
  excel.delete('Sheet1');


  List<String> dataList = [                                         //We write the names of your columns that will be created, this will be the first line. How many columns will be, so many names can be made
    "Name of 1st column",
    "Name of 2st column",
    "Name of 3st column",
    "Name of 4st column",
    "Name of 5st column and etc",
  ];
  sheetObject.insertRowIterables(dataList, 0);



  int rowCount = devices.length;                                      //arg 1
  for (int i = 1; i <= rowCount; i++) {sheetObject                                                                   //   Optional code, this is for creating a numbered column
        .cell(CellIndex.indexByColumnRow(columnIndex: 0, rowIndex: i))
        .value = i.toString();
  }



  devices.asMap().forEach((index, record) => sheetObject.insertRowIterables([                     // Create columns with fields from your documents, in order from left to right  // arg 1
        (index + 1).toString(),                                                                   // line numbering in order
        record.your_field.toString(),                                                              // Columns are created. your_field - change to your values ​​of field from the collection of documents.
        record.your_field.toString(),                                                               //record.your_field.toString() - Copy the string as many times as you need columns
        record.your_field.toString(),
        record.your_field.toString(),
      ], index + 1));



  sheetObject.appendRow([ ' ', ' ']);                                       //insert an empty line if you need to separate information from each other

  sheetObject.appendRow([ ' ', 'Итого:', ' ', '$totalPrice']);                //Here are my optional arguments. You can delete these lines or add the information you need to the line as well.  //Arg 3

  sheetObject.appendRow([' ', ' ']);

  sheetObject.appendRow([' ', 'Гар. Замены', ' ', '$waranty']);               //arg 4



  final now = DateTime.now();
  final formattedDate =
      '${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')}';            //Create document name: today's date + string from arg 2
  final filename = fileNameE + "_" + formattedDate + ".xlsx";                                                   //Arg 2


  final byteData = await excel.encode();
  final filePath ='/Your Folder Path in Firebase Storage/$filename';                                        //Replace with Your Firebase Storage Folder Path


  final storageReference = FirebaseStorage.instance.ref().child(filePath);
  final uploadTask = storageReference.putData(Uint8List.fromList(byteData!));                                       //Save to Firebase Storage


  try {
    await uploadTask;
    final url = await storageReference.getDownloadURL();
    return url.toString();
  } catch (error) {
    print(error.toString());
    return "ERROR";                                                                         //We return a string with URl or in case of an error with Error
  }
}
3