1. Introduzione
Lo scopo di questo codelab è farti capire come scrivere una funzione Cloud per reagire al caricamento di un file CSV in Cloud Storage, per leggerne il contenuto e utilizzarlo per aggiornare un foglio Google utilizzando l'API Sheets.

Può essere considerato come l'automazione di un passaggio di "importazione come CSV" altrimenti manuale. In questo modo, puoi analizzare i dati (magari prodotti da un altro team) in un foglio di lavoro non appena sono disponibili.
Ecco come appare l'implementazione :

2. Configurazione e requisiti
Configurazione dell'ambiente autonomo
- Accedi alla console Cloud e crea un nuovo progetto o riutilizzane uno esistente. Se non hai già un account Gmail o G Suite, devi crearne uno.
Ricorda l'ID progetto, un nome univoco tra tutti i progetti Google Cloud (il nome sopra è già stato utilizzato e non funzionerà per te, mi dispiace). In questo codelab verrà chiamato PROJECT_ID.
- Successivamente, dovrai abilitare la fatturazione in Cloud Console per utilizzare le risorse Google Cloud.
L'esecuzione di questo codelab non dovrebbe costare molto, se non nulla. Assicurati di seguire le istruzioni riportate nella sezione "Pulizia", che ti consiglia come arrestare le risorse in modo da non incorrere in addebiti oltre questo tutorial. I nuovi utenti di Google Cloud possono beneficiare del programma prova senza costi di 300$.
3. Crea e configura un foglio Google e abilita l'API
Innanzitutto, creiamo un nuovo documento Fogli (questo foglio può appartenere a qualsiasi utente). Una volta creato, ricorda il suo identificatore, che verrà utilizzato come variabile di ambiente per la funzione che scriveremo :

Dalla console GCP, attiva l'API Google Sheets nel progetto appena creato andando alla sezione "API e servizi" e poi a "Libreria API":

Nella sezione "IAM e amministrazione ", vai a"Service account " e prendi nota dell'email del service account predefinito di App Engine. Deve essere nel formato your-project-id@appspot.gserviceaccount.com. Naturalmente, puoi anche creare un tuo account di servizio dedicato a questa azione.

Infine, concedi a questo account di servizio i privilegi di modifica del foglio di lavoro utilizzando il pulsante "Condividi":

Con questa configurazione possiamo ora scrivere la nostra Cloud Function e configurarla per utilizzare questo service account. Sarà in grado di scrivere in questo documento del foglio di lavoro che abbiamo appena creato.
4. Crea un bucket di archiviazione
Creiamo il bucket che la nostra funzione cloud monitorerà per i nuovi file CSV.
Nella console, utilizza il menu a sinistra per andare a "Spazio di archiviazione"… :

… e crea un nuovo bucket chiamato csv2sheet-POSTFIX (sostituisci POSTFIX con qualcosa di univoco) con tutte le altre impostazioni impostate sui valori predefiniti :

5. Crea la funzione Cloud
Ora possiamo creare una funzione Cloud chiamata csv2sheet che viene attivata al caricamento di file in un bucket Cloud Storage specifico. Il codice verrà scritto in Node.js 8 con funzioni asincrone utilizzando l'editor incorporato direttamente nella console Cloud :

Assicurati di impostare il trigger su "Cloud Storage" e di modificare il nome del bucket in quello che hai creato nel passaggio precedente.
Aggiorna anche l'entry point della funzione che stiamo per scrivere a csv2sheet :

Ora modifica il corpo della funzione in :
- utilizzare le API Cloud Storage e Sheets
- contrassegna la funzione
csv2sheetcomeasync - recupera
fileNamedai metadati dell'evento Cloud Storage e deriva un nome per il nuovo foglio che creeremo :
const {google} = require("googleapis");
const {Storage} = require("@google-cloud/storage")
exports.csv2sheet = async (data, context) => {
var fileName = data.name;
// basic check that this is a *.csv file, etc...
if (!fileName.endsWith(".csv")) {
console.log("Not a .csv file, ignoring.");
return;
}
// define name of new sheet
const sheetName = fileName.slice(0, -4);
// TODO!
};
L'utilizzo di async qui è necessario per utilizzare await, come vedremo tra poco.
Alcune opzioni importanti durante la creazione di questa funzione includono (fai clic sul link "Altro" nella parte inferiore dello schermo) :
- Utilizza il menu a discesa per selezionare il service account descritto sopra.
- Definisci una variabile di ambiente denominata
SPREADSHEET_IDche deve corrispondere al documento del foglio che hai creato in precedenza :

Come ultimo passaggio di configurazione, ecco i contenuti di package.json con le API Cloud Storage e Google Sheets come due dipendenze che utilizzeremo (utilizza la scheda PACKAGE.JSON dell'editor incorporato della console) :
{
"name": "csv2sheet",
"version": "0.0.42",
"dependencies": {
"googleapis": "^51.0.0",
"@google-cloud/storage": "^5.0.1"
}
}
Una volta configurato tutto come descritto, fai clic su "Crea". Dopo un breve minuto, la funzione dovrebbe essere creata e sottoposta a deployment.
6. Configura l'autenticazione e l'API Sheets
Prima di scrivere altro codice nella nostra funzione Cloud utilizzando l'editor incorporato, dobbiamo bloccare la creazione di un'API Google Client con gli ambiti Storage e Fogli corretti (ricorda, fa parte di una funzione async).
Nell'editor di funzioni della console, fai clic su "MODIFICA" e aggiungi il seguente codice al corpo della funzione csv2sheet :
// block on auth + getting the sheets API object
const auth = await google.auth.getClient({
scopes: [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/devstorage.read_only"
]
});
Da qui possiamo creare un client API Google Sheets :
const sheetsAPI = google.sheets({version: 'v4', auth});
7. Utilizza l'API Sheets per creare un foglio vuoto
Con un client API Sheets possiamo creare un nuovo semplice foglio nel nostro documento, ma prima di andare avanti, ecco una breve nota sul vocabolario:
- un foglio di lavoro è il documento vero e proprio e viene fatto riferimento al suo identificatore (descritto sopra e visibile nell'URL del documento)
- un foglio è una delle schede del documento e può essere fatto riferimento al suo nome (il nome della scheda) o a un identificatore generato al momento della creazione del foglio
Tenendo presente questo, ecco una funzione che utilizza il client API Sheets per creare un foglio vuoto in posizione 2 (in genere dopo il "Foglio1 " predefinito), con 26 colonne, 2000 righe e la prima riga bloccata (aggiungila alla funzione utilizzando l'editor incorporato) :
function addEmptySheet(sheetsAPI, sheetName) {
return new Promise((resolve, reject) => {
const emptySheetParams = {
spreadsheetId: process.env.SPREADSHEET_ID,
resource: {
requests: [
{
addSheet: {
properties: {
title: sheetName,
index: 1,
gridProperties: {
rowCount: 2000,
columnCount: 26,
frozenRowCount: 1
}
}
}
}
]
}
};
sheetsAPI.spreadsheets.batchUpdate( emptySheetParams, function(err, response) {
if (err) {
reject("The Sheets API returned an error: " + err);
} else {
const sheetId = response.data.replies[0].addSheet.properties.sheetId;
console.log("Created empty sheet: " + sheetId);
resolve(sheetId);
}
}
);
});
}
Tieni presente che, anziché codificare in modo permanente il riferimento al foglio di lavoro, ci affidiamo alla variabile di ambiente SPREADSHEET_ID creata in precedenza.
Dobbiamo ricordare il sheetId per le ulteriori richieste effettuate a questo foglio specifico. Inoltre, il nome del foglio deve essere univoco e la creazione non andrà a buon fine se esiste già un foglio chiamato sheetName.
La funzione batchUpdate nell'API Fogli è un modo comune per interagire con i documenti ed è descritta qui.
8. Leggere i dati da un file CSV di archiviazione
Ora che abbiamo un posto dove scaricare i dati, sviluppiamo ulteriormente la nostra funzione cloud nell'editor incorporato e utilizziamo l'API Cloud Storage per recuperare i dati effettivi dal file appena caricato e archiviarli in una stringa:
function readCSVContent(sheetsAPI, file, sheetName) {
return new Promise((resolve, reject) => {
const storage = new Storage();
let fileContents = new Buffer('');
storage.bucket(file.bucket).file(file.name).createReadStream()
.on('error', function(err) {
reject('The Storage API returned an error: ' + err);
})
.on('data', function(chunk) {
fileContents = Buffer.concat([fileContents, chunk]);
})
.on('end', function() {
let content = fileContents.toString('utf8');
console.log("CSV content read as string : " + content );
resolve(content);
});
});
}
9. Compila il foglio appena creato
Ora è il momento di compilare il foglio che abbiamo creato utilizzando la stessa API client Sheets e i dati che abbiamo appena raccolto. Cogliamo l'occasione per aggiungere anche uno stile alle colonne del foglio (modificando le dimensioni del carattere della prima riga e mettendolo in grassetto) :
function populateAndStyle(sheetsAPI, theData, sheetId) {
return new Promise((resolve, reject) => {
// Using 'batchUpdate' allows for multiple 'requests' to be sent in a single batch.
// Populate the sheet referenced by its ID with the data received (a CSV string)
// Style: set first row font size to 11 and to Bold. Exercise left for the reader: resize columns
const dataAndStyle = {
spreadsheetId: process.env.SPREADSHEET_ID,
resource: {
requests: [
{
pasteData: {
coordinate: {
sheetId: sheetId,
rowIndex: 0,
columnIndex: 0
},
data: theData,
delimiter: ","
}
},
{
repeatCell: {
range: {
sheetId: sheetId,
startRowIndex: 0,
endRowIndex: 1
},
cell: {
userEnteredFormat: {
textFormat: {
fontSize: 11,
bold: true
}
}
},
fields: "userEnteredFormat(textFormat)"
}
}
]
}
};
sheetsAPI.spreadsheets.batchUpdate(dataAndStyle, function(err, response) {
if (err) {
reject("The Sheets API returned an error: " + err);
} else {
console.log(sheetId + " sheet populated with " + theData.length + " rows and column style set.");
resolve();
}
});
});
}
Questo codice deve essere aggiunto alla nostra funzione Cloud, che ora è completa al 99%.
Nota come i dati e lo stile vengono combinati come più requests in una singola chiamata API Sheets batchUpdate. In questo modo l'aggiornamento è più efficiente e atomico.
Tieni presente inoltre che definiamo un intervallo di modifica che corrisponde alle dimensioni del foglio che abbiamo creato. Ciò significa che i contenuti che superano le 26 colonne (il valore columnCount utilizzato durante la creazione del foglio) non verranno caricati con questo codice specifico.
Se tutto va bene, a questo punto puoi:
- salva la funzione aggiornata
- trascina un file CSV nel bucket
- visualizzare i dati corrispondenti nel foglio di lavoro.
10. Mettere insieme tutti i pezzi e testare il flusso
Le chiamate alle funzioni che abbiamo appena discusso possono essere effettuate come chiamate di blocco successive nella funzione csv2sheet originale:
const sheetId = await addEmptySheet(sheetsAPI, sheetName);
const theData = await readCSVContent(sheetsAPI, data, sheetName);
await populateAndStyle(sheetsAPI, theData, sheetId);
Se hai bisogno del codice sorgente completo della funzione, è disponibile qui (probabilmente è più facile ottenerlo tutto in un unico set).
Una volta che tutto è a posto, carica un file CSV nel bucket corretto e guarda il foglio di lavoro aggiornarsi con un nuovo foglio contenente i contenuti del file. Ecco un file CSV di esempio se non ne hai uno a portata di mano.

Prova a caricare diversi file nel bucket per vedere cosa succede.
11. È tutto. È ora di smantellare l'infrastruttura
Scherzo, non c'è alcuna infrastruttura da smantellare, è stato tutto fatto in modalità serverless.
Se vuoi, puoi eliminare la funzione cloud e il bucket che hai creato o anche l'intero progetto.
12. Passaggi successivi
Questo codelab si conclude qui. Ti ha guidato nei passaggi per ascoltare i caricamenti in un bucket Cloud Storage in una funzione Cloud Functions per aggiornare un foglio Google utilizzando l'API appropriata.
Ecco alcuni passaggi successivi :
- Consulta le guide illustrative di Cloud Functions (che includono alcune best practice).
- Segui uno dei tutorial di Cloud Functions.
- Esplora ulteriormente l'API Google Sheets
Se hai riscontrato problemi con questo codelab, non esitare a segnalarli utilizzando il link nell'angolo in basso a sinistra.
La tua opinione è molto importante per noi.