O problema não é o Google Sheets. O problema é quando você precisa cruzar a aba de DRE com o Balanço e a aba de premissas - e o resultado é uma cadeia de INDEX/MATCH que ninguém além de você consegue auditar, e que quebra quando alguém insere uma linha no meio. A integração Google Sheets DuckDB resolve a parte que o QUERY() nativo não resolve: um motor SQL completo sobre os dados ao vivo da sua planilha, sem exportar nada, sem CSV que já nasce desatualizado no momento em que sai do Sheets.
Este artigo responde ao que um analista financeiro precisa saber antes de adotar a abordagem - incluindo a pergunta mais prática: a saída do SQL pode ser referenciada pelas minhas fórmulas existentes?
DuckDB no Google Sheets vs. QUERY() e exportação CSV: o que cada abordagem resolve
Antes de entrar na arquitetura, um comparativo direto:
| Recurso | QUERY() nativo | Exportação CSV + DuckDB local | DuckDB integrado ao Sheets |
|---|---|---|---|
| JOIN entre abas diferentes | ✗ Não suporta | ✓ | ✓ |
Window functions (OVER PARTITION BY) | ✗ Não suporta | ✓ | ✓ |
| CTEs e subconsultas aninhadas | ✗ Limitado | ✓ | ✓ |
| Dados sempre atualizados (sem re-exportar) | ✓ | ✗ | ✓ |
| Saída referenciável por fórmulas normais | ✓ | ✗ Requer reimportação | ✓ |
| Rastreabilidade dos intervalos consultados | ✗ | ✗ | ✓ |
| Latência para 50.000 linhas | Baixa | Alta (ciclo manual) | Baixa-média |
O QUERY() é rápido e nativo, mas foi projetado para um único intervalo de origem - não faz JOIN entre abas distintas, não tem window functions. A exportação manual funciona tecnicamente, mas congela os dados no momento do export: distribuir um modelo na segunda com dados exportados na sexta é exatamente o tipo de problema que a integração embutida elimina. A abordagem nativa combina o melhor dos dois: SQL completo, dados sempre ao vivo.
Como funciona a integração DuckDB com Google Sheets
O QUERY() nativo executa dentro do motor de fórmulas do Sheets - limitado ao que esse motor expõe. O DuckDB roda como banco de dados separado em processo: lê os dados da planilha como entrada tabular e os trata como tabelas de um banco de dados. Sua planilha vira uma fonte de dados, não o ambiente de execução.
A implementação mais direta expõe os intervalos da planilha como fontes tabulares dentro do DuckDB via função de tabela - no ModelMonkey, essa função se chama sheet_range(), registrada como UDF no motor DuckDB:
SELECT
segmento,
periodo,
SUM(receita_liquida) AS receita_total,
SUM(cogs) AS custo_total,
SUM(receita_liquida - cogs) AS lucro_bruto,
ROUND(
100.0 * SUM(receita_liquida - cogs) / NULLIF(SUM(receita_liquida), 0),
1
) AS margem_bruta_pct
FROM sheet_range('DRE!B2:F500')
GROUP BY segmento, periodo
ORDER BY periodo, receita_total DESC
A função busca o intervalo no momento da execução e o retorna como fonte tabular tipada. Os tipos são inferidos dos dados: números chegam como DOUBLE, booleanos como BOOLEAN, colunas mistas como VARCHAR. De acordo com as DuckDB 1.2 release notes (março de 2025), a inferência de tipos foi aprimorada para lidar com colunas heterogêneas - relevante porque planilhas financeiras frequentemente têm cabeçalhos de texto misturados com valores numéricos na mesma coluna. Quando necessário, um cast explícito resolve em uma linha:
CAST(valor AS DOUBLE)
A pergunta que todo analista faz: a saída do SQL entra no meu modelo?
Sim - e essa é a distinção que define a utilidade prática da abordagem.
Quando uma query grava o resultado em uma aba de destino (por exemplo, Resumo_DRE), aquelas células se comportam exatamente como qualquer outro dado do Sheets. Você pode referenciar =Resumo_DRE!$C$15 numa fórmula de outra aba, usar o intervalo como fonte de gráfico, encadear com VLOOKUP ou INDEX/MATCH que busca premissas numa terceira aba.
O SQL resolve o JOIN e a agregação. As fórmulas existentes continuam como estão. Você não joga fora oito abas interligadas - você acrescenta uma camada de consulta que produz os números que suas fórmulas já esperavam encontrar.
Para um modelo em que o EBITDA calculado numa aba alimenta o DSCR de outra que alimenta o retorno do investidor, o fluxo fica assim:
- Query SQL agrega DRE multi-período por segmento → grava em
Resumo_DRE - Aba
Indicadoresusa=Resumo_DRE!C15para puxar EBITDA do período - Aba
Estrutura_Capitalusa=Indicadores!D8para calcular DSCR - Aba
Retorno_Investidorreferencia=Estrutura_Capital!E12
A cadeia de dependências continua intacta. O SQL elimina o JOIN manual; o modelo financeiro permanece sendo um modelo do Sheets.
Os limites que realmente importam
O Google Sheets comporta até 10 milhões de células por planilha, conforme Google Workspace Limits (abril de 2026). O DuckDB em si lida com volumes ordens de magnitude maiores, mas dentro da integração com Sheets você está limitado ao que a planilha comporta - o que, para modelos financeiros de empresas com R$ 50-200 milhões de receita, raramente é o gargalo real.
O que importa na prática são três restrições:
Tamanho da saída inline. Retornar 50.000 linhas diretamente numa célula é lento e desnecessário - o que você quer é o agregado. Uma integração bem calibrada limita resultados inline a cerca de 200 linhas; saídas maiores são gravadas diretamente em uma aba de destino especificada na query.
Latência de busca. O DuckDB roda em memória - rápido. O gargalo costuma ser a ida e volta à API do Sheets para buscar o intervalo. Para intervalos de até 5.000 linhas, a latência é imperceptível. Para intervalos maiores, conta-se em segundos.
Inferência de tipos em colunas mistas. Colunas com cabeçalhos de texto intercalados a valores numéricos ocasionalmente exigem cast explícito. É esperado e resolve com uma linha de SQL.
Vantagens da integração nativa DuckDB no Google Sheets sobre exportação manual
A abordagem de exportar-e-consultar - jogar em CSV, rodar o DuckDB localmente, reimportar - funciona tecnicamente, mas tem um problema estrutural: os dados ficam desatualizados no momento em que você exporta. Se seu modelo precisa se atualizar conforme a planilha muda (e modelos operacionais mudam todo dia), você volta às etapas manuais cada vez que os dados evoluem.
A integração embutida elimina essa etapa. A query sempre reflete o estado atual da planilha.
A segunda vantagem é rastreabilidade. Quando o DuckDB opera como parte de um fluxo de agente, o sistema registra quais intervalos foram acessados em cada execução. O agente consegue responder: "Consultei os intervalos DRE!B2:F500 e Premissas!A2:C50 e fiz join pela coluna periodo." Quando seu chefe perguntar "de onde veio esse número?", você tem a resposta explícita - não uma fórmula aninhada de seis níveis que exige reconstrução mental para depurar.
DRE multi-período no Google Sheets com DuckDB: um exemplo real
Considere um modelo financeiro com três abas: DRE_Detalhada (linhas de receita e custo por segmento e mês), Premissas (depreciação, taxa de imposto, custo de capital) e Ajustes (lançamentos não recorrentes por trimestre). Calcular EBITDA consolidado por segmento e período com fórmulas é genuinamente difícil - envolve SUMIFS encadeados, colunas auxiliares e tabelas dinâmicas que exigem atualização manual a cada fechamento.
Com DuckDB:
WITH base AS (
SELECT
d.segmento,
d.periodo,
SUM(d.receita_liquida) AS receita,
SUM(d.cogs) AS cogs,
SUM(d.despesas_operacionais) AS despesas_op,
SUM(COALESCE(a.ajuste_valor, 0)) AS ajustes_nao_recorrentes
FROM sheet_range('DRE_Detalhada!A2:G800') d
LEFT JOIN sheet_range('Ajustes!A2:D100') a
ON d.segmento = a.segmento
AND d.periodo = a.periodo
GROUP BY d.segmento, d.periodo
),
premissas AS (
SELECT depreciacao_mensal, taxa_imposto
FROM sheet_range('Premissas!A2:C3')
LIMIT 1
)
SELECT
b.segmento,
b.periodo,
b.receita,
b.receita - b.cogs AS lucro_bruto,
ROUND(100.0*(b.receita - b.cogs)/NULLIF(b.receita,0), 1) AS margem_bruta_pct,
b.receita - b.cogs - b.despesas_op AS ebit,
b.receita - b.cogs - b.despesas_op + p.depreciacao_mensal AS ebitda,
b.ajustes_nao_recorrentes
FROM base b, premissas p
ORDER BY b.periodo, b.segmento
O resultado grava em Resumo_DRE. A partir daí, a aba Indicadores faz =Resumo_DRE!E15 para puxar EBITDA do período - exatamente como faria com qualquer célula do Sheets. A query substitui a cadeia de SUMIFS; o modelo financeiro continua sendo um modelo do Sheets, com toda a cadeia de referências preservada.
Para uma empresa com R$ 80-150 milhões de receita anual, três segmentos e oito períodos, essa estrutura cabe confortavelmente dentro do limite de 10 milhões de células e roda em segundos. O equivalente em fórmulas levaria uma tarde para construir e outra para depurar quando alguém renomear uma aba.
FAQ: integração Google Sheets com DuckDB
O DuckDB consegue fazer JOIN entre abas diferentes do Google Sheets?
Sim. Cada aba é referenciada como tabela separada via notação A1 - por exemplo, sheet_range('DRE!A2:F500') e sheet_range('Premissas!A2:C50'). O JOIN é escrito em SQL padrão com JOIN ... ON. Não há limite no número de abas que podem ser cruzadas numa mesma query; o limite prático é o volume de dados que o Google Sheets comporta (10 milhões de células), não o motor DuckDB.
A saída de uma query DuckDB pode ser referenciada por fórmulas normais do Google Sheets?
Sim. Quando a query grava os resultados em uma aba de destino, aquelas células se comportam exatamente como qualquer dado no Sheets. Você pode usar =NomeAba!$C$15, VLOOKUP, INDEX/MATCH ou qualquer outra fórmula para consumir os resultados. O SQL produz os números; suas fórmulas existentes continuam lendo esses números normalmente. A cadeia de dependências do modelo - DRE → Indicadores → Estrutura de Capital → Retorno do Investidor - permanece intacta.
Qual é a diferença prática entre o QUERY() nativo e o DuckDB no Google Sheets?
O QUERY() opera sobre um único intervalo de origem, não suporta JOINs entre abas distintas e não tem window functions. O DuckDB é um motor OLAP completo com suporte a SQL padrão: CTEs, múltiplos JOINs, OVER (PARTITION BY ...), QUALIFY, HAVING e subconsultas. A diferença prática: QUERY() resolve análises simples de uma única tabela; DuckDB resolve análises que hoje exigem múltiplas abas, colunas auxiliares e tabelas dinâmicas manuais.
A integração lê os dados ao vivo ou precisa de exportação?
A integração embutida lê os dados da planilha no momento de execução - sem etapa de exportação intermediária. A query sempre reflete o estado atual das células, incluindo edições feitas segundos antes. Não é streaming em tempo real, mas elimina completamente a defasagem causada por exportação manual.
Há limite de linhas para as queries?
O DuckDB em si não impõe limite. O limite prático vem do Google Sheets (10 milhões de células por planilha) e do tamanho da saída inline: retornar dezenas de milhares de linhas diretamente numa célula é lento e, em modelos financeiros, desnecessário - o que importa é o agregado. A prática recomendada é queries que retornam dezenas a algumas centenas de linhas inline, com conjuntos maiores gravados em aba de destino.
Resumo
A integração DuckDB com Google Sheets adiciona SQL completo - JOINs entre abas, window functions, CTEs, GROUP BY multidimensional - sobre dados ao vivo da planilha, sem exportação manual. O limite de 10 milhões de células do Google Workspace define o teto prático, não o motor DuckDB. A saída das queries grava em abas de destino e pode ser referenciada por fórmulas normais do Sheets: a cadeia de dependências do modelo financeiro permanece intacta. As restrições práticas são o tamanho dos resultados inline (~200 linhas, com conjuntos maiores gravados em aba de destino) e a latência de busca para intervalos acima de 5.000 linhas.
O principal ganho não é velocidade de execução: é a substituição de cadeias inauditáveis de INDEX/MATCH por SQL que qualquer analista da equipe consegue ler, validar e explicar - inclusive quando o chefe perguntar de onde veio o número.
Escolha um plano do ModelMonkey - funciona no Google Sheets e no Excel.