Herramientas de usuario

Herramientas del sitio


codes:registroone

¡Esta es una revisión vieja del documento!


Formulario Google Apps Script - Monocurso


Inicios

Mediante este formulario, buscamos una adaptacion al googleForm pero más personal… Se debe crear un nuevo “sheet”, y desde allí acceder a la pestaña extensiones y seleccionar Apps Script.

Modulos

La app se resuelve en 5 modulos o archivos, cada uno con la extensión .gs o .html, propias de apps script.

server.gs

function doGet(e) {

return HtmlService.createTemplateFromFile('index')
  .evaluate()
  .setTitle('Curso para Docentes: Primeros Respondedores en Reanimación Cardiopulmonar Básica 1-Er Convocatoria');

}

function include(filename) {

return HtmlService.createHtmlOutputFromFile(filename).getContent();

}

Este módulo:

  • Recibe una petición web.
  • Carga index.html.
  • Procesa el template.
  • Define el título.
  • Permite incluir archivos HTML adicionales.
index.html

<!DOCTYPE html> <html lang=“en”> <head>

  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Curso para Docentes: Primeros Respondedores en Reanimación Cardiopulmonar Básica</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
  <?!= include('CSS'); ?>

</head> <body>

  <main>
      <!--<div class="form-container">
      <h3>Gracias por Comunicarse</h3>
        <p>Se ha superado el número de inscriptos en relación a las vacantes.</p>
        <p>Le invitamos a inscribirse para el <strong>Segundo Sementre 2025.</strong></p> -->
        <form id="registroForm">
              <div class="form-group">
                  <h2>Curso para Docentes: Primeros Respondedores en Reanimación Cardiopulmonar Básica</h2>
                  <h2>PRE-INSCRIPCIÓN AL CURSO</h2>
                  <h2>Año 2026 - Primer Convocatoria</h2>
                  <h3>Ministerio de Salud - Gobierno de La Pampa</h3>
                  <img src="https://drive.google.com/thumbnail?sz=w1000&id=1GTs5vaBO8jTcNZf8g8wBhoYqTn72RhN8" alt="Logo">
                  <p><strong>Importante:</strong> "Este documento tiene carácter de declaración jurada".</p>
              </div>
              <div class="form-group">
                  <label for="nombre">Nombres</label>
                  <input type="text" id="nombre" name="nombre" placeholder="Ingrese su nombre" required>
              </div>
              <div class="form-group">
                  <label for="apellido">Apellidos</label>
                  <input type="text" id="apellido" name="apellido" placeholder="Ingrese su apellido" required>
              </div>
              <div class="form-group">
                  <label for="dni">Documento</label>
                  <input type="text" id="dni" name="dni" placeholder="Ingrese su DNI" maxlength="8" required>
              </div>
              <div class="form-group">
                  <label for="telefono">Teléfono</label>
                  <input type="text" id="telefono" name="telefono" placeholder="Ingrese su teléfono" required>
              </div>
              <div class="form-group">
                  <label for="email">Email</label>
                  <input type="email" id="email" name="email" placeholder="Ingrese su email" required>
              </div>
              <div class="form-group">
                  <label for="localidad">Localidad</label>
                  <input type="text" id="localidad" name="localidad" placeholder="Ingrese su localidad" required>
              </div>
              <div class="form-group">
                  <label for="condicion">Condición</label>
                  <select id="condicion" name="condicion" required>
                      <option value="">Seleccione...</option>
                      <option value="Estudiante">Estudiante</option>
                      <option value="Docente">Docente</option>
                  </select>
              </div>
              
              <div id="docenteExtras" style="display: none;">
                  <div class="form-group">
                      <label for="institucion">Institución</label>
                      <input type="text" id="institucion" name="institucion" placeholder="Ingrese la institución">
                  </div>
                  <div class="form-group">
                      <label for="nivelEducativo">Nivel Educativo</label>
                      <select id="nivelEducativo" name="nivelEducativo">
                          <option value="">Seleccione...</option>
                          <option value="Inicial">Inicial</option>
                          <option value="Primario">Primario</option>
                          <option value="Secundario">Secundario</option>
                          <option value="Superior">Superior</option>
                          <option value="Otro">Otro</option>
                      </select>
                  </div>
              </div>
              <div class="form-group">
              <button type="submit">Enviar</button>
              </div>
          </form>
      </div>
  </main>
  <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.js"></script>
  <?!= include('JS'); ?>
  <script>
      document.getElementById('condicion').addEventListener('change', function() {
          var extras = document.getElementById('docenteExtras');
          extras.style.display = this.value === 'Docente' ? 'block' : 'none';
      });
  </script>

</body> </html>

Este archivo es la interfaz de usuario de tu Web App, que muestra un formulario dinámico con validación básica y campos condicionales, usando modularización de HTML, CSS y JS dentro de Apps Script.

CSS.html

<style>

body {

  font-family: Arial, sans-serif;
  margin: 0;
  padding: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  align-items: center;
  min-height: 100vh;
  background-color: #2a395e;
  color: #b6bed4;

}

.form-container {

  width: 90%;
  max-width: 600px;
  background: #FEFADC;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  align-items: center;
  box-shadow: -3px 3px 2px rgba(71, 69, 69, 0.269);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-content: center;
  margin: 15px 0;

}

img {

  width: 250px;

}

h2, h3, p {

  text-align: center;

}

h2 {

  font-size: 22px;

}

h3 {

  font-size: 20px;

}

.form-group {

  margin-bottom: 15px;
  align-items: center;
  display: flex;
  flex-direction: column;

}

label {

  display: block;
  margin-bottom: 5px;
  font-weight: bold;
  font-size: 18px;

}

input {

  width: 90%;
  padding: 10px;
  border: 1px solid #a9a4a4;
  border-radius: 4px;
  font-size: 16px;

}

select {

  width: 93%;
  padding: 10px;
  border: 1px solid #a9a4a4;
  border-radius: 4px;
  font-size: 16px;

}

button {

  margin-top: 25px;
  width: 90%;
  height: 60px;
  align-items: center;
  padding: 10px;
  background-color: #59bd68;
  color: rgb(255, 255, 255);
  border: none;
  border-radius: 4px;
  font-size: 30px;
  cursor: pointer;
  box-shadow: -3px 3px 2px rgba(71, 69, 69, 0.269);

}

button:hover {

  background-color: #06d425;
  color: black;

}

@media (max-width: 1024px) {

  .form-container {
      padding: 15px;
  }
  input, select {
      font-size: 28px;
  }
  button {
      font-size: 30px;
  }
  h2 {
      font-size: 50px;
  }
  h3 {
      font-size: 32px;
  }
  p {
      font-size: 28px;
  }
  label {
  margin-bottom: 10px;
  font-size: 32px;
  }

}

</style>

Este modulo o archivo hace el estilo de la web app

JS.html

<script> document.getElementById(“registroForm”).addEventListener(“submit”, function(event) {

event.preventDefault();
// Mostrar loading
const swalLoading = Swal.fire({
  title: 'Enviando datos...',
  text: 'Estamos procesando su solicitud. Por favor espere.',
  icon: 'info',
  showConfirmButton: false,
  allowOutsideClick: false,
  willOpen: () => {
    Swal.showLoading();
  }
});
// Obtener valores
const nombre = document.getElementById("nombre").value.trim();
const apellido = document.getElementById("apellido").value.trim();
const telefono = document.getElementById("telefono").value.trim();
const dni = document.getElementById("dni").value.trim();
const email = document.getElementById("email").value.trim();
const localidad = document.getElementById("localidad").value.trim();
const condicion = document.getElementById("condicion").value;
const institucion = document.getElementById("institucion").value.trim();
const nivelEducativo = document.getElementById("nivelEducativo").value;
// Validación básica
if (!nombre || !apellido || !telefono || !dni || !localidad || !condicion || !email) {
  swalLoading.close();
  Swal.fire({
    icon: 'error',
    title: 'Error',
    text: 'Por favor complete todos los campos.',
    confirmButtonText: 'Aceptar'
  });
  return;
}
// Validar DNI (8 números)
if (!/^\d{8}$/.test(dni)) {
  swalLoading.close();
  Swal.fire({
    icon: 'error',
    title: 'Error',
    text: 'El DNI debe tener 8 dígitos.',
    confirmButtonText: 'Aceptar'
  });
  return;
}
// Validar Teléfono (7 a 15 números)
if (!/^\d{7,15}$/.test(telefono)) {
  swalLoading.close();
  Swal.fire({
    icon: 'error',
    title: 'Error',
    text: 'El teléfono debe tener entre 7 y 15 dígitos.',
    confirmButtonText: 'Aceptar'
  });
  return;
}
// Validar Email
const emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
if (!emailPattern.test(email)) {
  swalLoading.close();
  Swal.fire({
    icon: 'error',
    title: 'Error',
    text: 'El formato del correo electrónico es inválido.',
    confirmButtonText: 'Aceptar'
  });
  return;
}
// Enviar a Apps Script
google.script.run
  .withSuccessHandler(function(response) {
    swalLoading.close();
    // 🚫 Cupos completos
    if (response === "cuposCompletos") {
      Swal.fire({
        icon: 'warning',
        title: 'Cupos Completos',
        text: 'Se alcanzaron las 400 plazas disponibles. Espere al próximo Semestre.',
        confirmButtonText: 'Aceptar',
        confirmButtonColor: '#d33'
      });
      // Desactivar botón
      document.getElementById("registroForm").reset();
      document.querySelector("button[type='submit']").disabled = true;
      return;
    }
    // ✅ Registro exitoso
    if (response === "registrado") {
      Swal.fire({
        icon: 'success',
        title: 'Registro Exitoso',
        text: 'Usted ha sido registrado correctamente.',
        confirmButtonText: 'Aceptar'
      });
      document.getElementById("registroForm").reset();
      document.getElementById("docenteExtras").style.display = "none";
      return;
    }
    // ⚠ DNI existente
    if (response === "existente") {
      Swal.fire({
        icon: 'warning',
        title: 'DNI ya registrado',
        text: 'Este DNI ya se encuentra inscripto.',
        confirmButtonText: 'Aceptar'
      });
      return;
    }
    // ⚠ Email existente
    if (response === "emailExistente") {
      Swal.fire({
        icon: 'warning',
        title: 'Email ya registrado',
        text: 'Este correo electrónico ya se encuentra inscripto.',
        confirmButtonText: 'Aceptar'
      });
      return;
    }
    // ❓ Respuesta inesperada
    Swal.fire({
      icon: 'error',
      title: 'Error',
      text: 'Respuesta inesperada del servidor.',
      confirmButtonText: 'Aceptar'
    });
  })
  .withFailureHandler(function(error) {
    swalLoading.close();
    Swal.fire({
      icon: 'error',
      title: 'Error',
      text: 'Hubo un error al procesar su solicitud.',
      confirmButtonText: 'Aceptar'
    });
  })
  .registrarConductor(
    nombre,
    apellido,
    telefono,
    dni,
    email,
    localidad,
    condicion,
    institucion,
    nivelEducativo
  );

}); </script>

Este modulo:

  • Intercepta el envío del formulario.
  • Valida los datos en el navegador.
  • Muestra un loading profesional.
  • Envía los datos al servidor (Apps Script).
  • Maneja todas las posibles respuestas del backend.
  • Muestra mensajes según el resultado.

Es el controlador frontend que valida datos, se comunica con Apps Script y maneja la lógica de inscripción según la respuesta del servidor.

validator.gs

function registrarConductor(nombre, apellido, telefono, dni, email, localidad, condicion, institucion, nivelEducativo) {

var ss = SpreadsheetApp.openById('1lKhiqQIAG-kaCbbUvDzbnU_RNCCQJfEQozIpbpLTUSk'); // ID de la hoja
var sheet = ss.getSheetByName('registro');

var registros = sheet.getDataRange().getValues();
var MAX_CUPOS = 400;
if ((registros.length - 1) >= MAX_CUPOS) {
  return "cuposCompletos";
}
// Verificar si el DNI ya existe (columna D - índice 3)
for (var i = 1; i < registros.length; i++) { // Empezamos en la fila 1 para omitir encabezados
  if (registros[i][3] == dni) { // Columna D (DNI)
    return "existente"; // DNI ya registrado
  }
}
// Verificar si el Email ya existe (columna F - índice 5)
for (var i = 1; i < registros.length; i++) { // Empezamos en la fila 1 para omitir encabezados
  if (registros[i][5] == email) { // Columna F (Email)
    return "emailExistente"; // Email ya registrado
  }
}
// Calcular el siguiente ID (columna A)
var id = registros.length;
// Agregar un nuevo registro (orden correcto según las columnas)
sheet.appendRow([
  id,              // A: ID
  nombre,          // B: NOMBRES
  apellido,        // C: APELLIDOS
  dni,             // D: DNI
  telefono,        // E: TELÉFONO
  email,           // F: EMAIL
  localidad,       // G: LOCALIDAD
  condicion,       // H: CONDICIÓN
  institucion,     // I: INSTITUCIÓN
  nivelEducativo   // J: NIVEL EDUCATIVO
]);
return "registrado"; // Confirmación de registro exitoso

}

Esta función es el controlador de negocio que valida cupos, previene duplicados y guarda la inscripción en Google Sheets, devolviendo estados específicos al frontend.

← Volver al Codes

codes/registroone.1771510832.txt.gz · Última modificación: por ggaita