GOOGLE_SHEETS - Integração com Planilhas do Google
O que é este Node?
O GOOGLE_SHEETS é o node responsável por integrar com o Google Sheets, permitindo ler, escrever, anexar e limpar dados em planilhas do Google de forma automatizada.
Por que este Node existe?
Planilhas são essenciais para armazenamento e análise de dados. O GOOGLE_SHEETS existe para:
- Armazenar dados estruturados: Salvar respostas de formulários, pedidos, leads
- Consultar informações: Ler preços, catálogos, dados de clientes
- Gerar relatórios: Exportar dados para análise em tempo real
- Integração universal: Google Sheets é acessível por toda equipe
- Automatização: Eliminar entrada manual de dados
Como funciona internamente?
Quando o GOOGLE_SHEETS é executado, o sistema:
- Autentica via OAuth2 com Google (access_token e refresh_token)
- Conecta à API do Google Sheets v4
- Executa operação solicitada (read, write, append, clear)
- Processa range especificado (ex: "Sheet1!A1:Z1000")
- Retorna dados ou confirmação da operação
- Se erro: Retorna mensagem de erro detalhada
Código interno (google-executors.service.ts:738-818):
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 sempre que precisar integrar com planilhas do Google:
Casos de uso
- Salvar leads: "Registrar nome, email e telefone de cada lead"
- Consultar catálogo: "Buscar preço de produto na planilha"
- Registro de atendimentos: "Logar todas as conversas com timestamp"
- Formulários dinâmicos: "Salvar respostas de pesquisa"
- Dashboard em tempo real: "Alimentar planilha para dashboards"
- Exportar relatórios: "Gerar relatório de vendas diário"
Quando NÃO usar GOOGLE_SHEETS
- Dados sensíveis sem criptografia: Use banco de dados seguro
- Altíssimo volume (>1000 req/min): Use banco de dados dedicado
- Processamento complexo: Use BigQuery para análise pesada
Parâmetros
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| operation | string | Sim | read, write, append, clear |
| spreadsheetId | string | Sim | ID da planilha (da URL) |
| range | string | Não | Range A1 notation (padrão: Sheet1!A1:Z1000) |
| values | array | Condicional | Dados para write/append (array de arrays) |
| accessToken | string | Sim | Token OAuth2 do Google |
| refreshToken | string | Sim | Refresh token OAuth2 do Google |
Operações Disponíveis
1. read - Ler dados da planilha
O que faz: Lê dados de um range específico da planilha.
Parâmetros obrigatórios: - spreadsheetId - accessToken - refreshToken
Parâmetros opcionais: - range (padrão: "Sheet1!A1:Z1000")
2. write - Escrever dados (sobrescrever)
O que faz: Sobrescreve dados em um range específico.
Parâmetros obrigatórios: - spreadsheetId - values - accessToken - refreshToken
Parâmetros opcionais: - range (padrão: "Sheet1!A1")
3. append - Anexar dados (adicionar no final)
O que faz: Adiciona dados no final da planilha automaticamente.
Parâmetros obrigatórios: - spreadsheetId - values - accessToken - refreshToken
Parâmetros opcionais: - range (padrão: "Sheet1!A1")
4. clear - Limpar dados
O que faz: Limpa todos os dados de um range específico.
Parâmetros obrigatórios: - spreadsheetId - accessToken - refreshToken
Parâmetros opcionais: - range (padrão: "Sheet1!A1:Z1000")
Exemplo 1: Salvar Lead em Planilha
Objetivo: Capturar nome e email e salvar na planilha automaticamente.
JSON para Importar
{
"name": "Salvar Lead no 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": "Pedir Nome",
"parameters": {
"message": "Qual é o seu nome?",
"variable": "nome"
}
}
},
{
"id": "email_1",
"type": "email",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Pedir Email",
"parameters": {
"message": "Qual é o seu email?",
"variable": "email"
}
}
},
{
"id": "google_sheets_1",
"type": "google_sheets",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Salvar na Planilha",
"parameters": {
"operation": "append",
"spreadsheetId": "1ABC123...XYZ",
"range": "Leads!A:B",
"values": [
["{{nome}}", "{{email}}"]
],
"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 com sucesso!\n\nNome: {{nome}}\nEmail: {{email}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1100, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "email_1" },
{ "source": "email_1", "target": "google_sheets_1" },
{ "source": "google_sheets_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Saída esperada:
Sistema: Qual é o seu nome?
Usuário: João Silva
Sistema: Qual é o seu email?
Usuário: joao@example.com
Sistema: ✅ Dados salvos com sucesso!
Nome: João Silva
Email: joao@example.com
Resultado na planilha: | Nome | Email | |------|-------| | João Silva | joao@example.com |
Exemplo 2: Ler Preços de Produtos
Objetivo: Consultar preço de produto na planilha.
JSON para Importar
{
"name": "Consultar Preço no 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": "Pedir Produto",
"parameters": {
"message": "Qual produto você deseja consultar?",
"variable": "produto"
}
}
},
{
"id": "google_sheets_1",
"type": "google_sheets",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Ler Preços",
"parameters": {
"operation": "read",
"spreadsheetId": "1ABC123...XYZ",
"range": "Produtos!A2:C100",
"accessToken": "{{google_access_token}}",
"refreshToken": "{{google_refresh_token}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Mostrar Resultado",
"parameters": {
"message": "📊 Dados carregados da planilha!\n\nTotal de produtos: {{rowCount}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "google_sheets_1" },
{ "source": "google_sheets_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Exemplo 3: Registro de Atendimento Completo
Objetivo: Salvar log completo de atendimento com timestamp.
JSON para Importar
{
"name": "Registrar Atendimento no 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": "Nome",
"parameters": {
"message": "Nome do cliente:",
"variable": "cliente_nome"
}
}
},
{
"id": "phone_1",
"type": "phone",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Telefone",
"parameters": {
"message": "Telefone:",
"variable": "cliente_telefone"
}
}
},
{
"id": "input_2",
"type": "input",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Assunto",
"parameters": {
"message": "Qual o assunto do atendimento?",
"variable": "assunto"
}
}
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Timestamp",
"parameters": {
"operation": "set",
"name": "timestamp",
"value": "{{$now}}"
}
}
},
{
"id": "google_sheets_1",
"type": "google_sheets",
"position": { "x": 1100, "y": 100 },
"data": {
"label": "Salvar Atendimento",
"parameters": {
"operation": "append",
"spreadsheetId": "1ABC123...XYZ",
"range": "Atendimentos!A:D",
"values": [
["{{timestamp}}", "{{cliente_nome}}", "{{cliente_telefone}}", "{{assunto}}"]
],
"accessToken": "{{google_access_token}}",
"refreshToken": "{{google_refresh_token}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 1300, "y": 100 },
"data": {
"label": "Confirmar",
"parameters": {
"message": "✅ Atendimento registrado!\n\nCliente: {{cliente_nome}}\nTelefone: {{cliente_telefone}}\nAssunto: {{assunto}}\nData/Hora: {{timestamp}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1500, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "phone_1" },
{ "source": "phone_1", "target": "input_2" },
{ "source": "input_2", "target": "variable_1" },
{ "source": "variable_1", "target": "google_sheets_1" },
{ "source": "google_sheets_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Resposta do Node
Operação read
{
"success": true,
"data": [
["Nome", "Email", "Telefone"],
["João Silva", "joao@example.com", "11999999999"],
["Maria Santos", "maria@example.com", "11888888888"]
],
"rowCount": 3
}
Operação write/append
{
"success": true,
"updatedCells": 2,
"updatedRows": 1
}
Operação clear
{
"success": true,
"message": "Range cleared successfully"
}
Como obter o spreadsheetId
O spreadsheetId está na URL da planilha:
https://docs.google.com/spreadsheets/d/1ABC123...XYZ/edit
^^^^^^^^^^^^^^
Este é o spreadsheetId
Formato A1 Notation (Range)
Exemplos de ranges válidos:
| Range | Descrição |
|---|---|
Sheet1!A1 |
Célula A1 da Sheet1 |
Sheet1!A1:B10 |
Células A1 até B10 |
Sheet1!A:A |
Coluna A inteira |
Sheet1!1:1 |
Linha 1 inteira |
Sheet1!A:C |
Colunas A até C |
Leads!A2:D |
Da linha 2 até última linha (colunas A-D) |
Formato de values (dados)
O parâmetro values deve ser um array de arrays:
// Uma linha com 3 colunas
[["João", "joao@email.com", "11999999999"]]
// Três linhas com 2 colunas cada
[
["Nome", "Email"],
["João", "joao@email.com"],
["Maria", "maria@email.com"]
]
Autenticação OAuth2
Para usar o Google Sheets, você precisa:
- Criar projeto no Google Cloud Console
- Habilitar Google Sheets API
- Criar credenciais OAuth2
- Obter tokens via fluxo OAuth2
- Salvar access_token e refresh_token
Os tokens podem ser armazenados em variáveis globais ou no contexto.
Boas Práticas
✅ SIM:
- Use
appendpara adicionar dados incrementalmente - Especifique range exato para melhor performance
- Valide dados antes de salvar na planilha
- Use headers na primeira linha (ex: Nome, Email, Telefone)
- Armazene tokens com segurança
❌ NÃO:
- Não exponha tokens em logs ou mensagens
- Não use
writequando querappend(sobrescreve dados) - Não faça múltiplas chamadas rápidas (rate limit)
- Não salve dados sensíveis sem criptografia
- Não use planilhas para dados ultra-críticos
Dicas
💡 Performance: Use ranges específicos ao invés de ler planilha inteira
💡 Append automático: append detecta automaticamente a próxima linha vazia
💡 USER_ENTERED: valueInputOption "USER_ENTERED" interpreta fórmulas automaticamente
💡 Rate Limits: Google Sheets API tem limite de 100 requisições/100 segundos por usuário
💡 Refresh Token: Salve o refresh_token para renovar access_token automaticamente
Troubleshooting
Erro: "The caller does not have permission"
Causa: Token sem permissões ou planilha não compartilhada
Solução:
1. Verifique se o token tem scope https://www.googleapis.com/auth/spreadsheets
2. Compartilhe a planilha com a conta de serviço
Erro: "Requested entity was not found"
Causa: spreadsheetId ou range inválido
Solução: Verifique o ID da planilha na URL e o range A1
Erro: "Invalid values"
Causa: Formato de values incorreto
Solução: Use array de arrays: [["valor1", "valor2"]]
Próximo Node
→ GOOGLE_DRIVE - Gerenciar arquivos no Google Drive → GOOGLE_CALENDAR - Integrar com Google Calendar → GOOGLE_DOCS - Manipular documentos do Google