GOOGLE SHEETS - Planilhas do Google
O que é este Node?
O GOOGLE SHEETS é o node responsável por integrar com o Google Planilhas permitindo ler, escrever, adicionar e limpar dados em planilhas do Google de forma programática.
Por que este Node existe?
Automatizar planilhas é essencial para produtividade. O GOOGLE SHEETS existe para:
- Centralizar dados: Armazenar informações coletadas em flows no Google Sheets
- Leitura de dados: Buscar informações de planilhas para usar em automações
- Relatórios automáticos: Gerar e atualizar relatórios sem intervenção manual
- Sincronização: Manter dados sincronizados entre WhatsApp e planilhas
- Colaboração: Permitir que equipes acessem dados atualizados em tempo real
Como funciona internamente?
Quando o GOOGLE SHEETS é executado, o sistema:
- Autentica usando OAuth2 com Google (access_token e refresh_token)
- Identifica a operação (read, write, append, clear)
- Conecta à API do Google Sheets v4
- Executa a operação especificada
- Retorna resultado com dados ou confirmação
- Se erro: Loga e lança exceção com detalhes
Código interno (productivity-executors.service.ts:18-94):
async executeGoogleSheets(data: any, variables: Record<string, any>): Promise<any> {
try {
this.logger.log('📊 [GOOGLE SHEETS] Executing operation');
const oauth2Client = new OAuth2Client(
process.env.GOOGLE_CLIENT_ID,
process.env.GOOGLE_CLIENT_SECRET,
process.env.GOOGLE_REDIRECT_URI
);
oauth2Client.setCredentials({
access_token: data.accessToken,
refresh_token: data.refreshToken,
});
const sheets = google.sheets({ version: 'v4', auth: oauth2Client });
switch (data.operation) {
case 'read':
const readResult = await sheets.spreadsheets.values.get({
spreadsheetId: data.spreadsheetId,
range: data.range || 'Sheet1!A1:Z1000',
});
return {
success: true,
data: readResult.data.values,
rowCount: readResult.data.values?.length || 0,
};
case 'write':
const writeResult = await sheets.spreadsheets.values.update({
spreadsheetId: data.spreadsheetId,
range: data.range || 'Sheet1!A1',
valueInputOption: 'USER_ENTERED',
requestBody: {
values: data.values,
},
});
return {
success: true,
updatedCells: writeResult.data.updatedCells,
updatedRows: writeResult.data.updatedRows,
};
case 'append':
const appendResult = await sheets.spreadsheets.values.append({
spreadsheetId: data.spreadsheetId,
range: data.range || 'Sheet1!A1',
valueInputOption: 'USER_ENTERED',
requestBody: {
values: data.values,
},
});
return {
success: true,
updatedCells: appendResult.data.updates?.updatedCells,
updatedRows: appendResult.data.updates?.updatedRows,
};
case 'clear':
await sheets.spreadsheets.values.clear({
spreadsheetId: data.spreadsheetId,
range: data.range || 'Sheet1!A1:Z1000',
});
return {
success: true,
message: 'Range cleared successfully',
};
default:
throw new Error(`Unknown Google Sheets operation: ${data.operation}`);
}
} catch (error) {
this.logger.error('Google Sheets execution error:', error);
throw error;
}
}
Quando você DEVE usar este Node?
Use GOOGLE SHEETS quando precisar integrar planilhas com seus flows:
Casos de uso:
- Cadastro em planilha: Salvar dados de formulários em planilha
- Leitura de configurações: Buscar parâmetros armazenados em planilha
- Relatório de atendimentos: Registrar cada conversa automaticamente
- Lista de produtos: Consultar catálogo armazenado em planilha
- Dashboard de métricas: Alimentar planilha com dados para análise
- Sincronização de estoque: Atualizar disponibilidade de produtos
Quando NÃO usar GOOGLE SHEETS:
- Dados sensíveis: Use banco de dados com criptografia
- Alto volume: Planilhas têm limites de performance
- Processamento complexo: Use CALCULATOR antes
Parâmetros Detalhados
operation (string, obrigatório)
O que é: Define qual operação será executada na planilha.
Valores possíveis:
- read: Ler dados de um range
- write: Sobrescrever dados em um range
- append: Adicionar dados ao final
- clear: Limpar um range
spreadsheetId (string, obrigatório)
O que é: ID único da planilha do Google Sheets.
Como obter: Na URL da planilha: https://docs.google.com/spreadsheets/d/[SPREADSHEET_ID]/edit
Flow completo para testar:
{
"name": "Teste GOOGLE SHEETS - Ler Planilha",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "sheets_1",
"type": "google_sheets",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Ler Planilha",
"parameters": {
"operation": "read",
"spreadsheetId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
"range": "Sheet1!A1:C10",
"accessToken": "{{google_access_token}}",
"refreshToken": "{{google_refresh_token}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Mostrar Dados",
"parameters": {
"message": "📊 Dados lidos: {{sheets_1.rowCount}} linhas"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "sheets_1" },
{ "source": "sheets_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
range (string, opcional)
O que é: Range de células no formato A1 notation (ex: "Sheet1!A1:C10").
Padrão: "Sheet1!A1:Z1000"
Flow completo para testar:
{
"name": "Teste GOOGLE SHEETS - Range Específico",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "sheets_1",
"type": "google_sheets",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Ler Apenas Cabeçalhos",
"parameters": {
"operation": "read",
"spreadsheetId": "{{planilha_id}}",
"range": "Sheet1!A1:E1",
"accessToken": "{{google_access_token}}",
"refreshToken": "{{google_refresh_token}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Mostrar Cabeçalhos",
"parameters": {
"message": "Cabeçalhos: {{sheets_1.data}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "sheets_1" },
{ "source": "sheets_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
values (array, requerido para write/append)
O que é: Array bidimensional com os valores a serem escritos.
Formato: [["linha1col1", "linha1col2"], ["linha2col1", "linha2col2"]]
Flow completo para testar:
{
"name": "Teste GOOGLE SHEETS - Adicionar Dados",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Nome",
"parameters": {
"message": "Qual seu nome?",
"variable": "nome"
}
}
},
{
"id": "input_2",
"type": "input",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Email",
"parameters": {
"message": "Qual seu email?",
"variable": "email"
}
}
},
{
"id": "sheets_1",
"type": "google_sheets",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Salvar em Planilha",
"parameters": {
"operation": "append",
"spreadsheetId": "{{planilha_id}}",
"range": "Sheet1!A1",
"values": [["{{nome}}", "{{email}}", "{{timestamp}}"]],
"accessToken": "{{google_access_token}}",
"refreshToken": "{{google_refresh_token}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Confirmar",
"parameters": {
"message": "✅ Dados salvos na planilha!"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1100, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "input_2" },
{ "source": "input_2", "target": "sheets_1" },
{ "source": "sheets_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
accessToken (string, obrigatório)
O que é: Token de acesso OAuth2 do Google para autenticação.
Como obter: Configure OAuth2 no Google Cloud Console e obtenha através do fluxo de autenticação.
refreshToken (string, obrigatório)
O que é: Token de refresh OAuth2 para renovar o access token automaticamente.
Parâmetros
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| operation | string | Sim | Operação: read, write, append, clear |
| spreadsheetId | string | Sim | ID da planilha do Google Sheets |
| range | string | Não | Range de células (padrão: Sheet1!A1:Z1000) |
| values | array | Sim* | Dados para write/append (array 2D) |
| accessToken | string | Sim | Token OAuth2 de acesso |
| refreshToken | string | Sim | Token OAuth2 de refresh |
*Obrigatório apenas para operações write e append
Exemplo 1: Cadastro de Leads em Planilha
Objetivo: Coletar dados de leads e salvar automaticamente em planilha.
JSON para Importar
{
"name": "Cadastro de Leads - Google Sheets",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "message_1",
"type": "message",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Boas-vindas",
"parameters": {
"message": "👋 Olá! Vamos fazer seu cadastro."
}
}
},
{
"id": "input_1",
"type": "input",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Nome",
"parameters": {
"message": "Qual é o seu nome completo?",
"variable": "nome"
}
}
},
{
"id": "email_1",
"type": "email",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Email",
"parameters": {
"message": "Qual é o seu email?",
"variable": "email"
}
}
},
{
"id": "phone_1",
"type": "phone",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Telefone",
"parameters": {
"message": "Qual é o seu telefone?",
"variable": "telefone"
}
}
},
{
"id": "sheets_1",
"type": "google_sheets",
"position": { "x": 1100, "y": 100 },
"data": {
"label": "Salvar em Planilha",
"parameters": {
"operation": "append",
"spreadsheetId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
"range": "Leads!A1",
"values": [["{{nome}}", "{{email}}", "{{telefone}}", "{{timestamp}}", "WhatsApp"]],
"accessToken": "{{google_access_token}}",
"refreshToken": "{{google_refresh_token}}"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 1300, "y": 100 },
"data": {
"label": "Confirmação",
"parameters": {
"message": "✅ Cadastro realizado com sucesso!\n\n📋 Seus dados:\nNome: {{nome}}\nEmail: {{email}}\nTelefone: {{telefone}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1500, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "message_1" },
{ "source": "message_1", "target": "input_1" },
{ "source": "input_1", "target": "email_1" },
{ "source": "email_1", "target": "phone_1" },
{ "source": "phone_1", "target": "sheets_1" },
{ "source": "sheets_1", "target": "message_2" },
{ "source": "message_2", "target": "end_1" }
]
}
Saída esperada:
Sistema: 👋 Olá! Vamos fazer seu cadastro.
Sistema: Qual é o seu nome completo?
Usuário: João Silva
Sistema: Qual é o seu email?
Usuário: joao@email.com
Sistema: Qual é o seu telefone?
Usuário: 11999887766
Sistema: ✅ Cadastro realizado com sucesso!
📋 Seus dados:
Nome: João Silva
Email: joao@email.com
Telefone: 11999887766
Exemplo 2: Consultar Catálogo de Produtos
Objetivo: Ler produtos de uma planilha e apresentar ao usuário.
JSON para Importar
{
"name": "Catálogo de Produtos - Google Sheets",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "sheets_1",
"type": "google_sheets",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Buscar Produtos",
"parameters": {
"operation": "read",
"spreadsheetId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
"range": "Produtos!A2:D100",
"accessToken": "{{google_access_token}}",
"refreshToken": "{{google_refresh_token}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Mostrar Catálogo",
"parameters": {
"message": "🛍️ CATÁLOGO DE PRODUTOS\n\nEncontramos {{sheets_1.rowCount}} produtos disponíveis!\n\nDigite o código do produto desejado."
}
}
},
{
"id": "input_1",
"type": "input",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Código",
"parameters": {
"message": "Digite o código do produto:",
"variable": "codigo_produto"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Confirmar",
"parameters": {
"message": "✅ Produto selecionado: {{codigo_produto}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1100, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "sheets_1" },
{ "source": "sheets_1", "target": "message_1" },
{ "source": "message_1", "target": "input_1" },
{ "source": "input_1", "target": "message_2" },
{ "source": "message_2", "target": "end_1" }
]
}
Saída esperada:
Sistema: 🛍️ CATÁLOGO DE PRODUTOS
Encontramos 15 produtos disponíveis!
Digite o código do produto desejado.
Sistema: Digite o código do produto:
Usuário: PROD001
Sistema: ✅ Produto selecionado: PROD001
Exemplo 3: Atualizar Status em Planilha
Objetivo: Atualizar status de um pedido específico na planilha.
JSON para Importar
{
"name": "Atualizar Status - Google Sheets",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Número do Pedido",
"parameters": {
"message": "Digite o número do pedido:",
"variable": "numero_pedido"
}
}
},
{
"id": "sheets_1",
"type": "google_sheets",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Atualizar Status",
"parameters": {
"operation": "write",
"spreadsheetId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
"range": "Pedidos!D2",
"values": [["Entregue"]],
"accessToken": "{{google_access_token}}",
"refreshToken": "{{google_refresh_token}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Confirmar",
"parameters": {
"message": "✅ Status do pedido {{numero_pedido}} atualizado para: ENTREGUE"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "sheets_1" },
{ "source": "sheets_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Saída esperada:
Sistema: Digite o número do pedido:
Usuário: #12345
Sistema: ✅ Status do pedido #12345 atualizado para: ENTREGUE
Resposta do Node
Operação READ:
{
"success": true,
"data": [
["Nome", "Email", "Telefone", "Data"],
["João Silva", "joao@email.com", "11999887766", "2025-01-15"],
["Maria Santos", "maria@email.com", "11988776655", "2025-01-15"]
],
"rowCount": 3
}
Operação WRITE/APPEND:
{
"success": true,
"updatedCells": 3,
"updatedRows": 1
}
Operação CLEAR:
{
"success": true,
"message": "Range cleared successfully"
}
Boas Práticas
✅ SIM:
- Use append para adicionar novos registros
- Use write para atualizar células específicas
- Especifique ranges precisos para melhor performance
- Use variáveis para armazenar spreadsheetId
- Implemente tratamento de erros com RETRY
❌ NÃO: - Não faça operações muito frequentes (respeite rate limits) - Não exponha tokens em logs ou mensagens - Não use ranges muito grandes (limite a 1000 linhas) - Não esqueça de validar dados antes de escrever
Dicas
💡 Range notation: Use formato "Sheet1!A1:C10" para especificar exatamente onde operar
💡 Performance: Operações em lote (múltiplas linhas) são mais eficientes que uma por vez
💡 Autenticação: Configure OAuth2 uma vez e reutilize tokens com refresh automático
💡 Backup: Sempre mantenha backup da planilha antes de operações de clear ou write massivo
💡 Validação: Use nodes de validação (EMAIL, PHONE, NUMBER) antes de salvar em planilha
Próximo Node
→ GOOGLE DRIVE - Gerenciar arquivos no Google Drive → NOTION - Integração com Notion → TRELLO - Gerenciar cards no Trello