lunes, 9 de diciembre de 2024

ImportRange (Problema y solución)

 La fórmula importrange es muy potente, ya que nos permite unir datos de diferentes hojas de cálculo y, con un poco de imaginación, ofrecer datos a diferentes usuarios sin que ellos tengan acceso a todos los datos. 

La sintaxis de la fórmula es =importrange("";""), donde en la primera parte se pone (entre comillas siempre) la url de la hoja de la que queremos importar datos y, donde en la segunda parte, ponemos el trozo de información o rango de datos que queremos. 

Por ejemplo,    =importrange("https://docs.google.com/spreadsheets/d/xxxxxxxxx";"Datos!A2:F")


Pero, y si cambiamos en la hoja de origen el nombre de la pestaña? O, y si introducimos una nueva columna y la columna A pasa a ser la B?

Probadlo y veréis que la fórmula deja de funcionar y nos obliga a cambiarla.

La solución es "intervalo con nombre". Si al rango Datos!A2:F le damos, por ejemplo un nombre tal como "Primeros_datos", podemos crear la fórmula tal que así:

=importrange("https://docs.google.com/spreadsheets/d/xxxxxxxxx";"Primeros_datos")


Ten en cuenta el detalle que se mantienen las comillas


domingo, 31 de marzo de 2024

Permitir al usuario crear un activador para una fecha concreta

 En una aplicación el usuario necesita guardar los datos desde varias hojas de cálculo (cada una de un grupo de alumnos) en una hoja aparte para poder gestionar históricos.

La labor que tenemos es crear un activador para que se haga de forma automática.

Existen activadores que se lanzan en una fecha concreta, pero nosotros queremos que sea no una sola vez, sino una fecha concreta cada año.

Nos encontramos que en google script no existe dicha opción ya que lo máximo que podemos automatizar es por meses.

Además, nos interesa que el usuario no tenga que aprender a crear activadores sino que le facilitemos un par de desplegables (para día y mes concretos) desde la hoja de cálculo.


He aquí el código que lo permite


function crear_o_cambiar_activador() {
  // Borramos todos los activadores
  borrar_todos_activadores()
  //creamos el activador dependiendo del día elegido
//(el mes se define dentro de la función - conseguir_datos-)
  // Como solamente existen activadores cada mes,
//hay que crear la comparación entre mes actual y mes elegido
//dentro de la función a activar
  // Hacemos un condicional y si no se cumple salimos de la función con return  
  var educakoa = SpreadsheetApp.getActiveSpreadsheet()
  var dia = educakoa.getRangeByName('dia').getValue()
ScriptApp.newTrigger('conseguir_datos').timeBased().onMonthDay(dia).create()
}

La función auxiliar que necesitamos para borrar los anteriores activadores es esta:
function borrar_todos_activadores() {
  var triggers = ScriptApp.getProjectTriggers()
  for (var i = 0; i < triggers.length; i++) {
    ScriptApp.deleteTrigger(triggers[i]);
  }
}

Este trozo necesitamos incluirlo en la función a activar, al principio del código
  var mes_actual = educakoa.getRangeByName('mes_actual').getValue()
  var mes_elegido = educakoa.getRangeByName('mes_elegido').getValue()
  if (mes_actual !=mes_elegido){return}


El problema se complica si tenemos otros activadores que no queremos borrar. 

Una función intermedia es esta que solamente borra los activadores basados en el tiempo:



function borrar_activadores_de_tiempo()
  {
    var activadores=ScriptApp.getProjectTriggers()
    for (cada in activadores){
          if (activadores[cada].getEventType()=="CLOCK"){
             ScriptApp.deleteTrigger(activadores[cada])
          }
    }
  }

 (en la función -crear_o_cambiar_activadores- sustituimos la fila - borrar_todos_activadores() -  por - borrar_activadores_de_tiempo()-


Como última mejoría, podemos utilizar esta función para borrar (borra activadores de tiempo que llamen a una función concreto, en este caso -conseguir_datos -

function borrar_activadores_de_tiempo_de_una_funcion_concreta()
  {
    var activadores=ScriptApp.getProjectTriggers()
    for (cada in activadores){
          Logger.log(activadores[cada].getHandlerFunction())
          if (activadores[cada].getEventType()=="CLOCK"){
            if (activadores[cada].getHandlerFunction()=='conseguir_datos'){
                       
            ScriptApp.deleteTrigger(activadores[cada])
          }}
    }
  }

 (en la función -crear_o_cambiar_activadores- sustituimos la fila - borrar_todos_activadores() -  por - borrar_activadores_de_tiempo_de_una_funcion_concreta()-


jueves, 25 de enero de 2024

Crear mensajes con posibilidad de confirmación

Metemos el mensaje en una variable y añadimos a msgBox "Browser.Buttons

var response= Browser.msgBox("¿Está usted segur@ que quiere mandar esta petición de información sobre\\n "+alumno+"?\\n\\n ¿De este grupo: "+grupo+" ?"+'\\n\\n',Browser.Buttons.OK_CANCEL); 

Para gestionar la respuesta, utilizamos la variable tal que así:

if (response=='ok'){ // Enviamos la petición} if (response=='cancel'){return} // Paramos el código

Crear PDF horizontal

El código que vamos a mostrar aquí no ha sido creado por nosotros, sino que lo hemos encontrado en Internet. Objetivo: Publicar una pesta...