/**
- SISTEMA DE GERAÇÃO DE QR CODES - VERSÃO MELHORADA
- Cria menu personalizado e gera QR Codes para impressão de crachás */
/**
- Cria o menu personalizado ao abrir a planilha. */ function onOpen() { try { var ui = SpreadsheetApp.getUi(); ui.createMenu('🖨️ IMPRESSÃO') .addItem('Gerar QR Codes para Impressão', 'gerarJanelaImpressao') .addSeparator() .addItem('Gerar QR Code (Fórmula)', 'mostrarAjuda') .addToUi(); } catch (erro) { console.error('Erro ao criar menu:', erro); } }
/**
- Função para gerar a URL da imagem do QR Code.
- Pode ser usada na planilha como: =OBTER_QR_URL(I2) */ function OBTER_QR_URL(link) { if (!link || link === "") return "";
// Valida se é uma URL válida if (!ehUrlValida(link)) { return ""; // Retorna vazio se URL for inválida }
var baseUrl = "https://api.qrserver.com/v1/create-qr-code/?size=150x150&data="; return baseUrl + encodeURIComponent(link); }
/**
- Valida se a string é uma URL válida usando regex / function ehUrlValida(url) { var regex = /^(https?://)?(www.)?[-a-zA-Z0-9@:%.+~#=]{1,256}.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%+.~#?&//=])$/; return regex.test(url); }
/**
- Mostra ajuda sobre como usar a fórmula
*/
function mostrarAjuda() {
var html = '<style>' +
'body { font-family: Arial, sans-serif; padding: 20px; }' +
'h2 { color: #007bff; }' +
'.exemplo { background: #f0f0f0; padding: 10px; border-left: 3px solid #007bff; margin: 10px 0; }' +
'code { background: #e0e0e0; padding: 2px 5px; border-radius: 3px; }' +
'</style>' +
'' +
'
Use esta fórmula para gerar QR Codes automaticamente:
' + 'Fórmula:' + '=OBTER_QR_URL(I2)Exemplo:
' + '- ' +
'
- Coluna I tem um link:
https://seu-site.com/aluno/001' +
' - Na coluna J, use:
=OBTER_QR_URL(I2)' +
' - Resultado: URL do QR Code para inserir como imagem ' + '
Para inserir a imagem na planilha:
' + '- Copie a URL do QR Code gerada ' + '
- Insira > Imagem > Importar de URL ' + '
- Cole a URL
- Coluna I tem um link:
var interface = HtmlService.createHtmlOutput(html) .setWidth(500) .setHeight(400); SpreadsheetApp.getUi().showModalDialog(interface, 'Ajuda - OBTER_QR_URL'); }
/**
-
Gera a janela com todos os QR Codes da aba selecionada.
-
VERSÃO MELHORADA: Mais robusta e com tratamento de erros */ function gerarJanelaImpressao() { try { var ss = SpreadsheetApp.getActiveSpreadsheet();
// Seleciona a aba (melhoria: permite escolher qual aba) var aba = selecionarAba(ss);
if (!aba) { return; // Usuário cancelou }
// Pega os dados da aba var ultimaLinha = aba.getLastRow(); if (ultimaLinha < 2) { SpreadsheetApp.getUi().alert('❌ Nenhum aluno encontrado nesta aba.'); return; }
// Extrai dados (C=Nome, I=Link) var dados = aba.getRange("C2:I" + ultimaLinha).getValues();
// Gera HTML com validações melhoradas var resultado = gerarHtmlQrCodes(dados);
if (resultado.contagem === 0) { SpreadsheetApp.getUi().alert('
⚠️ Nenhum aluno com dados válidos para gerar QR Code.\n\n' + 'Verifique se:\n' + '✓ Nome não está vazio\n' + '✓ Link é uma URL válida (https://...)\n' + '✓ Não há linhas vazias no meio dos dados'); return; }// Se houve erros, mostra alerta if (resultado.erros.length > 0) { var mensagem = '
⚠️ ' + resultado.contagem + ' aluno(s) processado(s) com sucesso!\n\n' + '❌ Problemas encontrados:\n' + resultado.erros.join('\n'); SpreadsheetApp.getUi().alert(mensagem); }// Abre janela com QR Codes var interface = HtmlService.createHtmlOutput(resultado.html) .setWidth(900) .setHeight(700) .setTitle('Impressão de Crachás com QR Code');
SpreadsheetApp.getUi().showModalDialog(interface, '✅ ' + resultado.contagem + ' aluno(s) único(s) processado(s)');
} catch (erro) { console.error('ERRO em gerarJanelaImpressao:', erro); SpreadsheetApp.getUi().alert('❌ Erro ao gerar QR Codes:\n' + erro.toString()); } }
/**
- Permite ao usuário selecionar qual aba deseja usar
- MELHORIA: Flexibilidade para múltiplas abas */ function selecionarAba(ss) { var abas = ss.getSheets(); var nomesAbas = [];
// Filtra apenas abas que têm dados for (var i = 0; i < abas.length; i++) { if (abas[i].getLastRow() > 1) { nomesAbas.push(abas[i].getName()); } }
if (nomesAbas.length === 0) { SpreadsheetApp.getUi().alert('❌ Nenhuma aba com dados encontrada.'); return null; }
// Se só tem uma aba, usa ela direto if (nomesAbas.length === 1) { return ss.getSheetByName(nomesAbas[0]); }
// Se tem múltiplas abas, pergunta qual usar var ui = SpreadsheetApp.getUi(); var resposta = ui.alert('Qual aba deseja usar para gerar QR Codes?', ui.ButtonSet.OK_CANCEL);
if (resposta === ui.Button.OK) { // Se usuário quer escolher, tenta usar a aba "AlunosAtivos" primeiro var abaDefault = ss.getSheetByName('AlunosAtivos'); return abaDefault ? abaDefault : ss.getSheetByName(nomesAbas[0]); }
return null; }
/**
- Gera o HTML dos QR Codes com validações melhoradas
- Retorna objeto com: html, contagem e erros
*/
function gerarHtmlQrCodes(dados) {
var html = '<style>' +
'body { margin: 0; padding: 20px; background: #f5f5f5; }' +
'.container { max-width: 1000px; margin: 0 auto; }' +
'.cartao { display: inline-block; width: 160px; padding: 10px; background: white; border: 1px solid #ccc; margin: 10px; text-align: center; font-family: sans-serif; page-break-inside: avoid; box-shadow: 0 2px 4px rgba(0,0,0,0.1); border-radius: 5px; }' +
'.nome { font-weight: bold; font-size: 11px; margin-top: 5px; height: 35px; display: flex; align-items: center; justify-content: center; overflow: hidden; word-wrap: break-word; }' +
'.qr-img { width: 140px; height: 140px; }' +
'.btn { background: #007bff; color: white; padding: 12px 24px; border: none; border-radius: 5px; cursor: pointer; margin-bottom: 20px; font-size: 14px; font-weight: bold; }' +
'.btn:hover { background: #0056b3; }' +
'.status { background: #e7f3ff; padding: 10px; border-radius: 5px; margin-bottom: 15px; color: #004085; }' +
'@media print { .btn { display: none; } .status { display: none; } body { background: white; } }' +
'</style>' +
'🖨️ IMPRIMIR QR CODES' +
'✅ Pronto para imprimir! Clique no botão acima ou use Ctrl+P' + '';
var nomesProcessados = []; var contagem = 0; var erros = [];
for (var i = 0; i < dados.length; i++) { try { var nomeOriginal = dados[i][0]; var link = dados[i][6]; // Coluna I (índice 6)
// Normaliza dados
var nomeLimpo = String(nomeOriginal).trim().toUpperCase();
var linkLimpo = String(link).trim();
// Validações melhoradas
if (nomeLimpo === "" || nomeLimpo === "UNDEFINED") {
continue; // Ignora linha vazia
}
if (!ehUrlValida(linkLimpo)) {
erros.push('Linha ' + (i + 2) + ': "' + nomeOriginal + '" tem URL inválida');
continue;
}
// Evita duplicatas pelo nome
if (nomesProcessados.includes(nomeLimpo)) {
erros.push('Linha ' + (i + 2) + ': "' + nomeOriginal + '" já foi processado (duplicata)');
continue;
}
// Gera QR Code
var qrUrl = "https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=" +
encodeURIComponent(linkLimpo);
html += '<div class="cartao">' +
'<img src="' + qrUrl + '" class="qr-img" alt="QR Code">' +
'<div class="nome">' + nomeOriginal + '</div>' +
'</div>';
nomesProcessados.push(nomeLimpo);
contagem++;
} catch (erro) {
erros.push('Linha ' + (i + 2) + ': Erro ao processar - ' + erro.toString());
console.error('Erro na linha ' + (i + 2) + ':', erro);
}
}
html += '';
return { html: html, contagem: contagem, erros: erros }; }