1. Introdução
O objetivo deste codelab é ensinar você a criar uma função do Cloud para reagir ao upload de um arquivo CSV no Cloud Storage, ler o conteúdo dele e usar esse recurso para atualizar um arquivo das Planilhas Google com a API Sheets.
Isso pode ser visto como a automação de uma "importação como CSV" manual etapa. Isso garante que você possa analisar os dados (talvez produzidos por outra equipe) em uma planilha assim que ela estiver disponível.
A implementação vai ficar assim :
2. Configuração e requisitos
Configuração de ambiente autoguiada
- Faça login no Console do Cloud e crie um novo projeto ou reutilize um existente. Crie uma se você ainda não tiver uma conta do Gmail ou do G Suite.
Lembre-se do código do projeto, um nome exclusivo em todos os projetos do Google Cloud. O nome acima já foi escolhido e não servirá para você. Faremos referência a ele mais adiante neste codelab como PROJECT_ID
.
- Em seguida, será necessário ativar o faturamento no Console do Cloud para usar os recursos do Google Cloud.
A execução deste codelab não será muito cara, se for o caso. Siga todas as instruções na seção "Limpeza", que orienta você sobre como encerrar recursos para não incorrer em cobranças além deste tutorial. Novos usuários do Google Cloud estão qualificados para o programa de US$ 300 de avaliação sem custos.
3. Criar e configurar um arquivo das Planilhas Google e ativar a API
Primeiro, vamos criar um novo documento do Planilhas (essa planilha pode pertencer a qualquer usuário). Uma vez criado, lembre-se de seu identificador. ele será usado como uma variável de ambiente para a função que escreveremos :
No Console do GCP, ative a API Google Sheets em seu projeto recém-criado em "APIs and Services". e depois em "Biblioteca de APIs" :
Na página "IAM e administrador" acesse "Contas de serviço" e anote o e-mail da conta de serviço padrão do App Engine. Ele precisa estar no formato your-project-id@appspot.gserviceaccount.com
. Também é possível criar sua própria conta de serviço dedicada a essa ação.
Por fim, basta conceder a essa conta de serviço privilégios de edição da planilha usando a opção botão :
Com essa configuração, já podemos escrever nossa função do Cloud e configurá-la para usar esta conta de serviço. Ela poderá gravar neste documento de planilha que acabamos de criar.
4. Criar um bucket de armazenamento
Vamos criar o bucket que nossa função do Cloud vai monitorar em busca de novos arquivos CSV.
No console, use o menu à esquerda para acessar "Armazenamento"... :
Crie um novo bucket com o nome csv2sheet-POSTFIX
e substitua POSTFIX por algo exclusivo com todas as outras configurações definidas com os valores padrão :
5. Criar a função do Cloud
Agora é possível criar uma função do Cloud chamada csv2sheet
, que é acionada quando há uploads de arquivos em um bucket específico do Cloud Storage. O código será escrito em Node.js 8 com funções assíncronas no editor in-line diretamente no console do Cloud :
Defina o gatilho como "Cloud Storage". e para ajustar o nome do bucket ao que você criou na etapa anterior.
Atualize também o ponto de entrada da função que estamos prestes a gravar em csv2sheet
:
Agora mude o corpo da função para :
- usar as APIs Cloud Storage e Sheets
- marque a função
csv2sheet
comoasync
. - receba o
fileName
dos metadados de evento do Cloud Storage e crie um nome para a nova planilha que vamos criar :
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!
};
O uso de async
aqui é necessário para usar await
, como veremos em breve.
Algumas opções importantes durante a criação dessa função incluem (clique no link "Mais" na parte inferior da tela) :
- Use o menu suspenso para selecionar a conta de serviço discutida acima
- Defina uma variável de ambiente chamada
SPREADSHEET_ID
que corresponda ao documento de planilha que você criou anteriormente :
Como etapa final da configuração, veja o conteúdo de package.json
com as APIs Cloud Storage e Planilhas Google como as duas dependências que usaremos (use a guia PACKAGE.JSON do editor in-line do console) :
{
"name": "csv2sheet",
"version": "0.0.42",
"dependencies": {
"googleapis": "^51.0.0",
"@google-cloud/storage": "^5.0.1"
}
}
Depois de configurar tudo conforme descrito, clique em "Criar" ! Após um breve minuto, a função será criada e implantada.
6. Configurar autenticação e API Sheets
Antes de escrevermos mais códigos na função do Cloud usando o editor in-line, precisamos bloquear a criação de uma API de cliente do Google com os escopos adequados do Storage e do Planilhas. Isso faz parte de uma função async
.
No editor de funções do console, clique em EDITAR. e adicione o seguinte código ao corpo da função 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"
]
});
A partir daí, podemos criar um cliente da API Sheets :
const sheetsAPI = google.sheets({version: 'v4', auth});
7. Usar a API Sheets para criar uma página vazia
Com um cliente da Sheets API, podemos criar uma nova planilha simples em nosso documento, mas antes de continuarmos, aqui está uma rápida observação sobre o vocabulário:
- uma planilha é o documento real e é referenciada por seu identificador (discutido acima e visível no URL do documento)
- uma planilha é uma das guias no documento e pode ser referenciada por seu nome (o nome da guia) ou por um identificador gerado na criação da página
Pensando nisso, esta é uma função que usa o cliente da API Sheets para criar uma planilha vazia na posição 2 (normalmente após a "Sheet1 padrão"), com 26 colunas e 2.000 linhas, com a primeira linha congelada (adicione-a à sua função usando o editor in-line) :
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);
}
}
);
});
}
Observe que, em vez de codificar a referência à planilha, usamos a variável de ambiente SPREADSHEET_ID
criada anteriormente.
Precisamos nos lembrar de sheetId
para outras solicitações feitas a essa página específica. Além disso, o nome da planilha precisa ser exclusivo. Se já houver uma página chamada sheetName
, a criação falhará.
A função batchUpdate
na API Sheets é uma maneira comum de interagir com documentos e está descrita aqui.
8. Ler dados de um arquivo CSV de armazenamento
Agora que temos um lugar para despejar os dados, vamos desenvolver a função do Cloud no editor in-line e usar a API Cloud Storage para extrair os dados reais do arquivo que acabou de ser enviado e armazená-los em uma string:
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. Preencher a planilha recém-criada
Agora é hora de preencher a planilha que criamos usando a mesma API de cliente do Planilhas e os dados que acabamos de coletar. Aproveitamos a oportunidade para também adicionar estilos às colunas da planilha (alterando o tamanho da fonte da linha superior e deixando-a em negrito) :
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();
}
});
});
}
Esse código deve ser adicionado à função do Cloud, que está 99% concluída.
Observe como os dados e o estilo são combinados como vários requests
em uma única chamada batchUpdate
da API Sheets. Isso torna a atualização mais eficiente e atômica.
Observe também que definimos um intervalo de edição que corresponde ao tamanho da página que criamos. Isso significa que o conteúdo que excede 26 colunas (o valor columnCount
usado ao criar a planilha) vai apresentar falha com esse código específico.
Se tudo correr bem, neste ponto você pode:
- salve a função atualizada
- solte um arquivo CSV no bucket
- ver os dados correspondentes aparecer em sua planilha!
10. Como reunir tudo e testar o fluxo
As chamadas para as funções que acabamos de discutir podem ser feitas como chamadas de bloqueio sucessivas na função csv2sheet
original:
const sheetId = await addEmptySheet(sheetsAPI, sheetName);
const theData = await readCSVContent(sheetsAPI, data, sheetName);
await populateAndStyle(sheetsAPI, theData, sheetId);
Se você precisar do código-fonte completo da função, acesse aqui (provavelmente mais fácil de encontrar tudo em um conjunto).
Quando tudo estiver no lugar, basta fazer upload de um arquivo CSV para o bucket correto e ver sua planilha ser atualizada com uma nova planilha com o conteúdo do arquivo. Este é um exemplo de arquivo CSV, caso você não tenha um.
Faça upload de vários arquivos para o bucket e veja o que acontece.
11. Pronto! Hora de eliminar a infraestrutura
Brincadeira, não há infraestrutura para desmontar. Tudo isso é feito sem servidor.
Se quiser, você pode excluir a função do Cloud e o bucket que você criou ou até mesmo todo o projeto.
12. A seguir
Isso conclui este codelab mostrando as etapas para detectar uploads de um bucket do Cloud Storage em uma função do Cloud e atualizar uma planilha Google usando a API apropriada.
Confira o que fazer a seguir:
- Confira os guias de instruções do Cloud Functions (inclui algumas práticas recomendadas).
- Consulte um dos tutoriais do Cloud Functions.
- Conheça mais a API Google Sheets
Se você tiver problemas com este codelab, informe-os no link no canto inferior esquerdo.
Seu feedback é muito importante.