error when form values go to specific sheet

38 views
Skip to first unread message

muzzol mussol

unread,
Jul 9, 2026, 6:30:06 PM (12 days ago) Jul 9
to Google Apps Script Community
Hi,

I'm trying to write form values to a weekly sheet.

My code is something like this:


function onFormSubmit(e) {
var uservalues = e.values;
// var uservalues = ["one", "two", "potato"];

const book = SpreadsheetApp.openById("xxxxxxx");
var weekNum = Utilities.formatDate(new Date(), "GMT", "w");
var weekDay = Utilities.formatDate(new Date(), "GMT", "EEE");

var sheetWeekName = ("Week " + weekNum);

// check if exist
var sheetWeek = book.getSheetByName(sheetWeekName);
if (sheetWeek) {
Logger.log("Already exists: " + sheetWeekName);
} else {
Logger.log("Creating new sheet");
sheetWeek = book.insertSheet(sheetWeekName);
}

sheetWeek.appendRow(uservalues);
}





And I'm getting this error:

Exception: The rowContents passed to appendRow() must be nonempty.

If I test it with manual uservalues and launch the function it works, new sheet is created and values are appended.
But when I submit a form I get the error mentioned.

I'm pretty new to Apps Scripts, sorry if I'm missing something obvious.

mussol


Message has been deleted

Kildere S Irineu

unread,
Jul 10, 2026, 4:39:52 AM (11 days ago) Jul 10
to Google Apps Script Community

O erro ocorre porque e.values está chegando como undefined ou vazio. Isso normalmente acontece quando o gatilho foi criado no Google Formulários, pois nesse tipo de gatilho os dados ficam em e.response, não em e.values.

e.values existe no evento de envio de formulário disparado pela planilha de respostas. O objeto e só é fornecido quando o gatilho executa a função automaticamente; ao clicar em Executar no editor, ele não existe.

Também há um segundo problema possível: ao criar a nova aba, é necessário guardar a aba criada na mesma variável usada posteriormente pelo appendRow().

Solução recomendada: script vinculado à planilha de respostas

Coloque este código no Apps Script aberto pela planilha que recebe as respostas:

/** * Executada por um gatilho instalável: * "Da planilha" > "Ao enviar formulário". * * @param {GoogleAppsScript.Events.SheetsOnFormSubmit} e */ function onFormSubmit(e) { // Verifica se a função foi chamada corretamente pelo gatilho. if (!e || !Array.isArray(e.values) || e.values.length === 0) { console.error('Evento inválido ou sem valores:', e); throw new Error( 'Nenhum valor foi recebido. Configure um gatilho "Da planilha > Ao enviar formulário".' ); } const spreadsheetId = 'COLE_O_ID_DA_PLANILHA_AQUI'; const book = SpreadsheetApp.openById(spreadsheetId); // Usa o fuso horário configurado no projeto. const timeZone = Session.getScriptTimeZone(); // Usa a data do envio, quando disponível. const submittedAt = e.values[0] instanceof Date ? e.values[0] : new Date(); const weekNumber = Utilities.formatDate( submittedAt, timeZone, 'ww' ); const sheetWeekName = `Semana ${weekNumber}`; // Procura a aba da semana. let sheetWeek = book.getSheetByName(sheetWeekName); // Cria a aba quando ela ainda não existe. if (!sheetWeek) { console.log(`Criando a aba: ${sheetWeekName}`); sheetWeek = book.insertSheet(sheetWeekName); } else { console.log(`A aba já existe: ${sheetWeekName}`); } // appendRow exige um array não vazio. sheetWeek.appendRow(e.values); console.log( `Resposta adicionada em ${sheetWeekName}: ${JSON.stringify(e.values)}` ); }

O método appendRow() recebe um array com os conteúdos da linha. Caso esse array esteja vazio ou indefinido, a exceção informada é gerada.

Configure o gatilho

No editor do Apps Script:

  1. Abra Gatilhos, no ícone de relógio.
  2. Clique em Adicionar gatilho.
  3. Escolha a função onFormSubmit.
  4. Em origem do evento, escolha Da planilha.
  5. Em tipo de evento, escolha Ao enviar formulário.
  6. Salve e autorize o script.

Não teste essa função diretamente pelo botão Executar. Para testes manuais, use uma função separada:

function testOnFormSubmit() { const fakeEvent = { values: [ new Date(), 'Um', 'Dois', 'Batata' ] }; onFormSubmit(fakeEvent); }
Caso o script esteja vinculado diretamente ao formulário

Nesse caso, utilize e.response.getItemResponses():

/** * Executada por um gatilho instalável criado no Google Formulários: * "Do formulário" > "Ao enviar formulário". * * @param {GoogleAppsScript.Events.FormsOnFormSubmit} e */ function onFormSubmit(e) { if (!e || !e.response) { throw new Error( 'Resposta não recebida. Esta função precisa ser executada pelo gatilho do formulário.' ); } const spreadsheetId = 'COLE_O_ID_DA_PLANILHA_AQUI'; const book = SpreadsheetApp.openById(spreadsheetId); const timeZone = Session.getScriptTimeZone(); const submittedAt = e.response.getTimestamp(); // Monta uma linha contendo data/hora e respostas. const userValues = [ submittedAt, ...e.response .getItemResponses() .map(itemResponse => itemResponse.getResponse()) ]; const weekNumber = Utilities.formatDate( submittedAt, timeZone, 'ww' ); const sheetWeekName = `Semana ${weekNumber}`; let sheetWeek = book.getSheetByName(sheetWeekName); if (!sheetWeek) { sheetWeek = book.insertSheet(sheetWeekName); } sheetWeek.appendRow(userValues); }

Portanto, a correção depende da origem do gatilho:

  • Gatilho criado na planilha: use e.values.
  • Gatilho criado no formulário: use e.response.
  • Execução manual pelo editor: crie um evento de teste, pois o Apps Script não fornece e automaticamente.
Log_scrip.txt

muzzol

unread,
Jul 10, 2026, 8:39:37 AM (11 days ago) Jul 10
to google-apps-sc...@googlegroups.com
Muito obrigado for the detailed response.

I still don't get when e.values is used and when e.response (or e.responses) is used.
I find a lot of examples using both, is quite confusing.

Thanks for your time,

Mussol


Missatge de Kildere S Irineu <kilder...@gmail.com> del dia dv., 10 de jul. 2026 a les 10:39:
--
You received this message because you are subscribed to the Google Groups "Google Apps Script Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-c...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/google-apps-script-community/2310d750-88eb-4ba1-b8a6-eed0306a946en%40googlegroups.com.


--
========================
     ^ ^
     O O
    (_ _)
muzzol(a)muzzol.com
========================
No atribueixis qualitats humanes als ordinadors.
No els hi agrada.
========================
"El gobierno español sólo habla con terroristas, homosexuales y catalanes, a ver cuando se decide a hablar con gente normal"
Jiménez Losantos
========================

Kildere S Irineu

unread,
Jul 10, 2026, 9:11:30 AM (11 days ago) Jul 10
to Google Apps Script Community

Olá,

Essa é uma dúvida muito comum entre quem está começando com Google Apps Script. A confusão acontece porque existem dois gatilhos diferentes chamados "Ao enviar formulário", e cada um fornece um objeto de evento (e) diferente.

A regra é simples:


Onde o gatilho está instalado?
O que existe em e?
Utilize
Na planilha que recebe as respostas
e.values, e.range, e.namedValues
e.values
No Google Formulários
e.response
e.response

Essa diferença existe porque cada serviço trabalha de forma diferente.


1. Quando usar e.values

Se o gatilho foi criado na planilha de respostas, o Apps Script já sabe qual linha acabou de ser adicionada.

Exemplo:

function onFormSubmit(e) { Logger.log(e.values); }

Supondo que o formulário recebeu:

Nome: João Idade: 25 Cidade: Recife

e.values será aproximadamente:

[ "10/07/2026 09:15:22", "João", "25", "Recife" ]

Ou seja, trata-se de um array contendo todos os valores da linha.

Assim, você pode acessar os dados por posição:

var nome = e.values[1]; var idade = e.values[2];

Ou simplesmente gravar a linha em outra planilha:

sheet.appendRow(e.values);

Esse é exatamente o formato esperado pelo método appendRow().


2. O que é e.namedValues

Quando o gatilho está na planilha, também existe:

e.namedValues

Esse objeto utiliza os títulos das perguntas como chave:

{ "Nome": ["João"], "Idade": ["25"], "Cidade": ["Recife"] }

Assim, você pode acessar os valores pelo nome da pergunta:

var nome = e.namedValues["Nome"][0];

Essa abordagem costuma ser mais segura quando a ordem das perguntas pode mudar.


3. Quando usar e.response

Se o gatilho foi criado diretamente no Google Formulários, o objeto recebido é diferente.

Nesse caso, utiliza-se:

function onFormSubmit(e) { Logger.log(e.response); }

e.response não é um array.

Ele é um objeto do tipo FormResponse, que possui diversos métodos, como:

e.response.getTimestamp(); e.response.getRespondentEmail(); e.response.getItemResponses();

Por exemplo:

function onFormSubmit(e) { var respostas = e.response.getItemResponses(); respostas.forEach(function(r) { Logger.log(r.getItem().getTitle()); Logger.log(r.getResponse()); }); }

Resultado:

Nome João Idade 25 Cidade Recife

Perceba que, nesse caso, o Apps Script trabalha com perguntas e respostas, e não com uma linha pronta da planilha.


Por que existem dois objetos diferentes?

Cada serviço possui uma visão diferente dos dados.

Google Sheets

A planilha trabalha com linhas:

Timestamp | Nome | Idade | Cidade

Por isso o Apps Script fornece:

e.values

que representa exatamente essa linha.

Google Forms

O formulário trabalha com perguntas e respostas:

Pergunta 1 Pergunta 2 Pergunta 3

Por isso ele fornece:

e.response

que representa toda a resposta enviada pelo usuário.


Existe e.responses?

Não.

No gatilho padrão de envio de formulário, o correto é:

e.response

(no singular)

Para obter todas as respostas utiliza-se:

var respostas = e.response.getItemResponses();
Qual utilizar?

Se o objetivo é copiar os dados enviados para outra planilha, como no exemplo:

sheetWeek.appendRow(userValues);

o mais simples é criar o gatilho na planilha de respostas e utilizar:

var userValues = e.values;

Já se o objetivo for trabalhar diretamente com o formulário (por exemplo, obter o e-mail do respondente, identificar as perguntas ou acessar outros detalhes da submissão), então deve-se utilizar:

e.response
Resumo
Situação
Utilize
Copiar a linha enviada para outra planilha
e.values
Inserir dados usando appendRow()
e.values
Trabalhar com perguntas e respostas do formulário
e.response
Obter os títulos das perguntas
e.response.getItemResponses()
Acessar o e-mail ou a data da resposta
e.response
e.responses
Não existe nesse gatilho
Dica para depuração

Uma ótima forma de entender quais propriedades o objeto e possui é registrar seu conteúdo durante a execução do gatilho:

function onFormSubmit(e) { console.log(JSON.stringify(e, null, 2)); }

Lembre-se de que essa função deve ser executada pelo gatilho de envio do formulário, e não pelo botão Executar do editor. Dessa forma, será possível visualizar exatamente quais propriedades (values, namedValues, response, etc.) estão disponíveis naquele contexto.


Kildere Sobral Irineu

Analista e Desenvolvedor de Sistemas e Agentes de IA

Administração de Empresas – MBA Gestão  

https://www.linkedin.com/in/kilderesobralirineu/

Reply all
Reply to author
Forward
0 new messages