Código.gs
function doGet() {
var form = HtmlService.createTemplateFromFile("Principal");
return form.evaluate()
.setTitle("Consulta de Notas")
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function Chamar(Arquivo){
return HtmlService
.createHtmlOutputFromFile(Arquivo)
.getContent();
}
Principal.html
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Consulta de Notas</title>
<style>
:root{
--bg1:#004d7a;
--bg2:#008793;
--bg3:#00bf72;
--card-bg: rgba(255,255,255,0.12);
--glass: rgba(255,255,255,0.15);
}
html,body{height:100%;margin:0;font-family: "Segoe UI", Roboto, Arial, sans-serif;}
body{
margin:0;
color:#fff;
background:#ffffff;
}
.container{
width:100%;
min-height:100vh;
box-sizing:border-box;
background:linear-gradient(
135deg,
#004d7a,
#008793,
#00bf72
);
padding:20px;
}
.header{
display:flex;
align-items:center;
gap:12px;
margin-bottom:12px;
}
.brand {
width:56px;
height:56px;
border-radius:8px;
background:rgba(255,255,255,0.12);
display:flex;
align-items:center;
justify-content:center;
font-weight:bold;
font-size:18px;
}
h1{font-size:1.2rem;margin:0;}
.form-row{
display:flex;
gap:10px;
margin-top:12px;
align-items:center;
}
input[type="text"]{
flex:1;
padding:12px 14px;
border-radius:10px;
border:none;
font-size:1rem;
outline:none;
background:#ffffffdd;
color:#111;
}
.btn {
padding:11px 14px;
border-radius:10px;
border:none;
font-weight:700;
cursor:pointer;
min-width:120px;
}
.btn-primary{ background:#00bf72; color:#fff; }
.btn-secondary{ background:#f5f5f5; color:#111; }
.resultado{
margin-top:18px;
}
.disciplina{ display:flex; justify-content:space-between; gap:10px; padding:6px 0; border-bottom: 1px dashed rgba(255,255,255,0.06); }
.disciplina:last-child{ border-bottom: none; }
.smallnote{ font-size:0.85rem; opacity:0.9; margin-top:8px; }
/* responsivo */
@media (max-width:520px){
.header{ gap:8px; }
.brand{ width:44px; height:44px; font-size:16px; }
h1{ font-size:1rem; }
.form-row{ flex-direction:column; align-items:stretch; }
.btn{ width:100%; min-width:unset; }
}
.btn-link {
background: #ffd700; /* Fundo amarelo para destacar */
border: 1px solid #e6c200; /* Borda para contraste */
color: #333; /* Texto escuro para legibilidade */
cursor: pointer;
font-size: 0.9rem; /* Proporcional à fonte do texto circundante */
padding: 4px 8px; /* Tamanho ajustado para retangular e proporcional */
border-radius: 4px; /* Cantos ligeiramente arredondados */
margin-left: 6px;
height: 24px; /* Altura fixa para consistência */
display: flex;
align-items: center;
justify-content: center;
}
/* Container para permitir scroll lateral na tabela em celulares */
.table-responsive {
width: 100%;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
margin-top: 10px;
border-radius: 8px;
}
/* Ajustes na tabela para não esmagar o texto */
table{
width:100%;
border-collapse:collapse;
min-width:500px;
background:#ffffff;
color:#111;
font-size:13px;
}
td{
padding:4px 6px;
border:none !important;
vertical-align:middle;
white-space:normal;
word-break:break-word;
}
/* Linhas suaves */
tr:nth-child(even){
background:#f7f7f7;
}
/* Imagem da planilha */
.img-planilha{
max-width:55px;
max-height:55px;
border-radius:4px;
object-fit:cover;
}
/* Botão amarelo */
.btn-tabela{
background:#ffd400;
color:#111 !important;
text-decoration:none !important;
padding:3px 8px;
border-radius:3px;
font-weight:bold;
display:inline-block;
font-size:11px;
border:1px solid #c7a800;
}
/* Estilo para os links dentro da tabela */
.btn-tabela {
background: #ffd700;
color: #111 !important;
text-decoration: none !important;
padding: 4px 8px;
border-radius: 4px;
font-weight: bold;
display: inline-block;
font-size: 0.8rem;
}
.barra-container{
width:100px;
height:14px;
background:#e0e0e0;
border-radius:20px;
overflow:hidden;
}
.barra-nota{
height:100%;
border-radius:20px;
box-shadow: inset 0 1px 2px rgba(255,255,255,0.5);
transition:0.3s;
}
.grupo{
cursor:pointer;
font-weight:bold;
background:#dff5ff !important;
}
.item{
display:none;
}
.seta{
color:#1e88e5;
font-weight:bold;
margin-right:8px;
}
@media (max-width:768px){
.container{
padding:10px;
}
table{
font-size:11px;
}
td{
padding:3px;
white-space:normal;
word-break:break-word;
}
.img-planilha{
max-width:40px;
max-height:40px;
}
.barra-container{
width:70px;
}
.btn-tabela{
font-size:10px;
padding:2px 5px;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<div class="brand">ESC</div>
<div>
<h1>Consulta de Notas por Matrícula</h1>
<div class="smallnote">Digite a matrícula (ex.: 222345 ou 152345) — o sistema escolherá a aba conforme a matrícula.</div>
</div>
</div>
<div class="form-row">
<input id="matricula" type="text" placeholder="Digite a matrícula" autocomplete="off" />
<button id="btnPesquisar" class="btn btn-primary">PESQUISAR</button>
<button id="btnLimpar" class="btn btn-secondary">LIMPAR</button>
</div>
<div id="mensagem" style="margin-top:12px; color:#ffdddd;"></div>
<div id="resultado" class="resultado" style="display:none;"></div>
<script>
const btnPesquisar = document.getElementById('btnPesquisar');
const btnLimpar = document.getElementById('btnLimpar');
const mensagem = document.getElementById('mensagem');
const resultado = document.getElementById('resultado');
btnPesquisar.addEventListener('click', function(){
mensagem.textContent = "";
resultado.style.display = "none";
const matricula = document.getElementById('matricula').value.trim().replace(/\s/g, "");
if(!matricula){
mensagem.textContent = "Por favor, digite a matrícula.";
return;
}
google.script.run.withSuccessHandler(function(res){
if(!res || res === "Não encontrado!"){
mensagem.textContent = "Matrícula não encontrada!";
return;
}
// 🔥 Adicionamos a div 'table-responsive' em volta da tabela
let html = "<div class='table-responsive'><table>";
let grupoAtual = -1;
res.forEach((linha, i)=>{
if(linha.tipo === "G"){
grupoAtual = i;
html += `
<tr
class="grupo"
onclick="toggleGrupo(${grupoAtual}, this)">
`;
}else if(linha.tipo === "I"){
html += `
<tr
class="item grupo-${grupoAtual}">
`;
}else{
html += `
<tr>
`;
}
linha.dados.forEach((celula,j)=>{
html += "<td>";
if(j === 0 && linha.tipo === "G"){
html += `
<span class="seta">
▶
</span>
`;
}
if(celula.link){
// VERIFICA SE É IMAGEM
const isImage =
celula.imagem ||
celula.link.match(/\.(jpeg|jpg|png|gif|webp)$/i) ||
celula.link.includes("imgur.com") ||
celula.link.includes("googleusercontent");
if(isImage){
html += `
<img
src="${celula.link}"
class="img-planilha"
>
`;
}else{
html += `
<a href="${celula.link}"
target="_blank"
class="btn-tabela">
${celula.texto || "CLIQUE AQUI"}
</a>
`;
}
}else{
const valor = parseFloat(
String(celula.texto).replace(",", ".")
);
/*
E = índice 3
(porque agora a coluna A foi removida do HTML)
*/
if(j === 3 && !isNaN(valor)){
const porcentagem = valor * 10;
let corBarra = "";
if(valor < 5){
corBarra = "#e53935";
}else if(valor < 8){
corBarra = "#f9a825";
}else{
corBarra = "#1e88e5";
}
html += `
<div class="barra-container">
<div
class="barra-nota"
style="
width:${porcentagem}%;
background:${corBarra};
">
</div>
</div>
`;
}else{
html += interpretarBBCode(
celula.texto || ""
);
}
}
html += "</td>";
});
html += "</tr>";
});
html += "</table></div>"; // Fechamos a div e a tabela
resultado.innerHTML = html;
resultado.style.display = "block";
}).PesquisarNotas(matricula);
}); // 🔴 FECHAMENTO CORRETO
btnLimpar.addEventListener('click', function(){
document.getElementById('matricula').value = "";
mensagem.textContent = "";
resultado.style.display = "none";
resultado.innerHTML = ""; // 🔴 limpa também o conteúdo
});
</script>
<script>
function interpretarBBCode(texto){
if(!texto){
return "";
}
// Negrito
texto = texto.replace(
/\[b\](.*?)\[\/b\]/gis,
"<strong>$1</strong>"
);
// Itálico
texto = texto.replace(
/\[i\](.*?)\[\/i\]/gis,
"<em>$1</em>"
);
// Sublinhado
texto = texto.replace(
/\[u\](.*?)\[\/u\]/gis,
"<span style='text-decoration:underline'>$1</span>"
);
// Tamanho da fonte
texto = texto.replace(
/\[fs=(\d+)\](.*?)\[\/fs\]/gis,
"<span style='font-size:$1px'>$2</span>"
);
// Cor da fonte
texto = texto.replace(
/\[color=(.*?)\](.*?)\[\/color\]/gis,
"<span style='color:$1'>$2</span>"
);
// Cor de fundo
texto = texto.replace(
/\[bg=(.*?)\](.*?)\[\/bg\]/gis,
"<span style='background:$1;padding:2px 4px;border-radius:3px'>$2</span>"
);
// Centralizar
texto = texto.replace(
/\[center\](.*?)\[\/center\]/gis,
"<div style='text-align:center'>$1</div>"
);
// Direita
texto = texto.replace(
/\[right\](.*?)\[\/right\]/gis,
"<div style='text-align:right'>$1</div>"
);
// Quebra de linha
texto = texto.replace(
/\[br\]/gi,
"<br>"
);
return texto;
}
function toggleGrupo(id, elemento){
const linhas =
document.querySelectorAll(
".grupo-" + id
);
let aberto = false;
linhas.forEach(linha => {
if(
linha.style.display ===
"table-row"
){
linha.style.display =
"none";
}else{
linha.style.display =
"table-row";
aberto = true;
}
});
const seta =
elemento.querySelector(".seta");
if(seta){
seta.textContent =
aberto ? "▼" : "▶";
}
}
</script>
</body>
</html>
Macro.gs
var url = "https://docs.google.com/spreadsheets/d/1ktIfJBBAqgMpXq5YNOFjMIlufGwJOqebQWUvYJgYD3Q/edit?usp=sharing";
function PesquisarNotas(matricula) {
try {
matricula = matricula.toString().trim();
var planilha = SpreadsheetApp.openByUrl(url);
var aba = "";
// Define qual aba usar
aba = "Página" + matricula;
var guia = planilha.getSheetByName(aba);
if (!guia) return "Não encontrado!";
var intervalo = guia.getDataRange();
var valores = intervalo.getDisplayValues();
var richText = intervalo.getRichTextValues();
var formulas = intervalo.getFormulas();
var resultado = [];
// Colunas a serem ocultadas (Q até Z)
const colunasOcultas = [16,17,18,19,20,21,22,23,24,25]; // Q=16, R=17, ..., Z=25
for (var i = 0; i < valores.length; i++) {
var linha = {
tipo: valores[i][0], // Coluna A (G ou I)
dados: []
};
for (var j = 1; j < valores[i].length; j++) {
// 🔥 IGNORA as colunas Q até Z
if (colunasOcultas.includes(j)) continue;
var texto = valores[i][j];
var formula = formulas[i][j];
var link = richText[i][j] ? richText[i][j].getLinkUrl() : null;
/* VERIFICA IMAGE() */
if(formula && formula.includes('IMAGE("')){
var match = formula.match(/IMAGE\("([^"]+)"/);
if(match && match[1]){
linha.dados.push({
texto:"",
link:match[1],
imagem:true
});
}else{
linha.dados.push({
texto:texto,
link:null
});
}
}else if(link){
linha.dados.push({
texto:texto || "CLIQUE AQUI",
link:link
});
}else{
linha.dados.push({
texto:texto,
link:null
});
}
}
resultado.push(linha);
}
return resultado;
} catch (e) {
Logger.log(e);
return "Não encontrado!";
}
}