You have unlimited access as a PRO member
You are receiving a free preview of 3 lessons
Your free preview as expired - please upgrade to PRO
Contents
Recent Posts
- Object Oriented Programming With TypeScript
- Angular Elements Advanced Techniques
- TypeScript - the Basics
- The Real State of JavaScript 2018
- Cloud Scheduler for Firebase Functions
- Testing Firestore Security Rules With the Emulator
- How to Use Git and Github
- Infinite Virtual Scroll With the Angular CDK
- Build a Group Chat With Firestore
- Async Await Pro Tips
CSV Exports From Firestore Database With Cloud Functions
Episode 69 written by Jeff DelaneyA common business requirement for a professional app is to export data as comma separated values, or CSV format. Data formatted this way can be used by spreadsheet software like Microsoft Excel and Google Docs, but it can also be used as input to many popular machine learning libraries. It this lesson, I will show you how to export a Firestore collection in CSV format using Firebase Cloud Functions and a Storage Bucket.
How to Export CSV from a Firebase Cloud Function
Our goal is to export the orders collection into an excel spreadsheet. The user can generate reports by clicking a button and each one is timestamp’d and saved to a Firebase Storage bucket.
The data structure is very simple - my primary goal is to show you process of converting Firestore data to CSV.ordersCollection (the data we want to report)
-- orderDoc
reportsCollection (the cloud function trigger)
-- reportDoc
And here’s how it works from the user perspective
- User clicks “generate CSV report button” in Angular which creates a new report document, initially set a status of processing.
- A loading spinner appears, the cloud function does its thing, then a link with download URL appears.
Dependencies
firebase init functions |
The fs-extra package is an extension for the NodeJS file system. It does one thing that is really helpful - it turns a file write operation into a Promise. The core Node file system uses callbacks, which becomes problematic in the cloud function promise chain.
To handle converting JS objects to CSV, I am using the json2csv package for node.
Firebase storage is not available in the admin SDK at the time of this article. Maybe this will change in the future, but for now, we can use the @google-cloud/storage
package directly to interact with the storage bucket.
index.js
This is a fairly complex set of asynchronous events, so let’s break it down step by step.
- Make references to data locations in firestore and cloud storage.
- Query the entire orders collection
- Convert the snapshot to an array of objects, then convert to CSV.
- Write the file to cloud function tmp storage
- Upload the file to Firebase Cloud Storage
- Update the report document to complete in Firestore.
const functions = require('firebase-functions'); |
const functions = require('firebase-functions'); |
You should now see an uploaded report in Cloud Storage when the function is triggered.
Angular App
Now that we have a cloud function, let’s build an Angular app that can take advantage of it.
Note: I seeded the database with an orders collection for the purposes of this lesson. They just have a price, product, and image.
App Component
In the app component, I am looping over the orders (only for presentation purposes), then looping over the reports below them. The user can click a button to save a report, which puts the whole process into motion by invoking the function. A loading spinner is shown when the report status is processing.
import { Component, OnInit } from '@angular/core'; |
In the HTML, we just loop over the report observable and create button for the user to generate the report.
<button (click)="requestReport()"> |
ReportLink Component
ng generate component report-link |
You may be wondering how we get the report’s download URL from the Firebase storage bucket.
We could save the URL directly to Firestore, but that’s not entirely necessary. We can request the storage URL asynchronously with the getDownloadURL()
method. This approach ensures that the download URL is always fresh. The method returns a promise, but I have converted it to an Observable to make it more Angular-ish.
Consider moving the firebase SDK import and the link code to an Angular service to make this code reusable.
import { Component, OnInit, Input } from '@angular/core'; |
Now we can simply set the link href
as the unwrapped observable download URL.
<a class="button is-info" |
The End
This method can be used to format all sorts of different reports beyond CSV. You could use a similar pattern with a libraries like PDFKit or OfficeGen to create other non-web-friendly documents.