jueves, 3 de junio de 2021
Limpiar la denonimación de los intervalos con nombre importados de otra hoja de cálculo
Rangos con nombre (intervalos con nombre) "GetRangeByName"
Como ya explique en un artículo antiguo (Referencias a pestañas y/o celdas en código) es muy interesante utilizar los intervalos con nombre creándolos en la hoja de cálculo y referenciándolos en el código con .getRangeByName()
Como comenté en dicho artículo, la ventaja más evidente es que, aunque el usuario cambie el nombre de la pestaña o el lugar de una celda, el código sigue apuntando a donde le hemos dicho que apunte.
Para dejar más claro el problema:
Si utilizo en el código
var pestana = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('configuración')
corro el peligro que deje de funcionar si alguien cambia el nombre de pestaña, un peligro que se escapa de nuestras manos
Peor aún, si utilizo en el código esta referencia:
var resultado = pestana.getRange('B2').getValue()
Dejará de funcionar en cuanto añadamos alguna columna o fila antes de la B o de la fila 2
Para evitar todo esto, la solución es crear intervalos con nombre en la hoja de cálculo y referenciarlos tal que así:
var pestana= SpreadsheetApp.getActiveSpreadsheet().getRangeByName('configuración')
var resultado = pestana.getRangeByName('el_de_la_celda_B2')
Pero... Nos hemos encontrado con una buena noticia y una mala en relación a estos rangos con nombre:
- La buena: Cuando copiamos una pestaña en otra hoja de cálculo ("Copiar en" de la pestaña), los intervalos con nombre también se copian.. pero con un nombre mezcla de la pestaña y el nombre antiguo.
- La mala: El código de referencia a estos rangos con nombre a veces no funciona, no encuentra dicho intervalo con nombre. La cuestión es que a veces funciona y a veces no. Y la única solución que he encontrado es borrar dicho intervalo y volverlo a crear.
jueves, 27 de mayo de 2021
Saltar errores y continuar con el código
Estoy haciendo código para conseguir quitar todos los permisos a un correo concreto en todos los archivos y subcarpetas de una carpeta dada.
Para conseguir quitar permisos el código necesita una dirección de correo tal que así:
archivo.removeEditor(email)
Metiendo esta orden en un bucle que recorra todos los archivos nos permite conseguir nuestro objetivo.
Pero, a veces, resulta que no encuentra dicho correo y el código da error y NO SIGUE ADELANTE, se para.
Un truco para saltar por encima es utilizar este tratamiento de errores de Javascript:
try{archivo.removeEditor(email)}
catch(e){}
Gracias a envolver nuestro código en try{} y añadir después catch(e){} logramos que el error no nos pare.
Entre las llaves de la segunda parte catch(e){}, podemos poner código que solamente corra cuando se da el error.
jueves, 4 de marzo de 2021
Recorrer carpetas y documentos en DRIVE
Este artículo tiene como objetivo mostrar el código básico para trabajar con Drive, es decir, para recorrer todos los archivos y subcarpetas de drive.
Ultimamente he estado trabajando con los permisos que damos a carpetas y documentos drive.
Nuestra recomendaciones son:
- No utilizar permisos en carpetas (la herencia es difícil de controlar)
- No utilizar permisos globales, salvo que haya una razón importante
- Utilizar google groups para gestionar los permisos
Debido a estas recomendaciones, ha habido centros que se han encontrado con la tarea de cambiar un montón de permisos anteriores, como por ejemplo: infinidad de carpetas, subcarpetas y documentos que tienen permiso de "cualquiera de educación con el enlace". Otro ejemplo es tener infinidad de permisos en documentos obsoletos a los que queremos hacer desaparecer, sin tener que meter horas yendo documento por documento y persona por persona quitando estos permisos.
Gracias al código, todas estas necesidades se pueden hacer de forma automática, simplemente dando la dirección de una carpeta y el código se ocupa de limpiar de permisos todo lo que contenga dicha carpeta.
He hecho diferentes funciones, según el objetivo a conseguir, pero en todas se ha repetido el proceso básico de ir recorriendo todos los documentos y subcarpetas incluidas en una carpeta dada. Por eso, me parece interesante hacer una especie de código básico que controle este proceso y, que con diferentes variantes, nos permita hacer infinidad de cosas con drive.
Lo vamos a hacer en tres funciones entrelazadas: función inicial, función para archivos y función para subcarpetas. La unión es la siguiente:
Empezamos con la función inicial y de ahí llamamos a la función de los archivos. Desde archivos llamamos a la función de subcarpetas. En esta última, en la función subcarpetas volvemos a llamar a la función archivos (que vuelve a llamar a subcarpetas, que vuelve a llamar a archivos..... hasta que no hay más)
Este recorrido es fundamental para poder recorrer todos los archivos y subcarpetas que haya dentro de una carpeta.
Dentro de cada función estas son las líneas básicas:
Inicio:
// Conseguimos la carpeta principal
var carpeta_global =DriveApp.getFolderById(id_general)
// Llamamos a la función archivos
archivos(carpeta_global)
Archivos:
// Conseguimos todos los archivos de la carpeta
var archivos_global = carpeta_global.getFiles()
// Los recorremos todos con un bucle
while (archivos_global.hasNext()){
// Apuntamos a cada archivo (dentro del bucle)
var archivo= archivos_global.next();
// Con cada archivo podemos hacer lo que necesitemos, por ejemplo,
archivo. setSharing(DriveApp.Access.PRIVATE, DriveApp.Permission.NONE) //quitamos todos los permisos globales
}
// Una vez terminado con todos los archivos de esta carpeta llamamos a la función de subcarpetas, fuera del bucle
subcarpeta(carpeta_global)
Subcarpetas:
// Conseguimos todas las subcarpetas que haya dentro
var sub_carpetas = carpeta_global.getFolders()
// Hacemos el bucle para recorrerlas
while (sub_carpetas.hasNext()) {
// Apuntamos a cada una de ellas
var subcarpeta = sub_carpetas.next()
// Con cada subcarpeta podemos hacer muchas cosas, por ejemplo,
subcarpeta.removeEditor(correo) // Eliminamos un editor concreto
// y dentro del bucle llamamos a la función archivos, PERO, pasando cada subcarpeta, en vez de la carpeta_global
archivos(subcarpeta)
lunes, 4 de enero de 2021
Conseguir fecha legible
En otros artículos anteriores ya he hablado de las fechas y como tratarlas, pero siempre buscando trucos para conseguirlo.
Ahora os traigo, lo que espero que sea, la solución definitiva. Además con alternativas para diferentes idiomas:
Euskaraz egitean, deklinazio arazo txiki bat dugu. Hortaz, bide luzetxoa egin behar dugu:
var marca_temporal_ano= marca_temporal.toLocaleString('eu-ES',{year: 'numeric'})
var marca_temporal_dia= marca_temporal.toLocaleString('eu-ES',{day:'2-digit'})
Logger.log(marca_temporal_ano+'(e)ko '+marca_temporal_mes+'ren '+marca_temporal_dia)
En castellano, nos basta con definir cada parte de la fecha en una única orden:
var mi_marca =marca_temporal.toLocaleString('es-ES',{year: 'numeric',month:'long',day:'2-digit'})
Logger.log(mi_marca)
En inglés americano, igual que en castellano, lo hacemos en una sola orden:
var my_time = marca_temporal.toLocaleString('en-US',{year: 'numeric',month:'long',day:'2-digit'})
Logger.log(my_time)
En inglés británico, cambiamos simplemente de 'en-US' a 'en-GB'
var my_time = marca_temporal.toLocaleString('en-GB',{year: 'numeric',month:'long',day:'2-digit'})
Logger.log(my_time)
Referencia:
Artículos antiguos:
jueves, 17 de diciembre de 2020
Insertar logo en pestaña (código y proceso extraño)
Estoy haciendo una aplicación para crear actas y necesito que en la pestaña de cada acta aparezca como encabezado el logo del centro.
Quiero, además, que la imagen del logo esté en drive.
Como cada pestaña con cada acta se crea por código, no me vale el menú insertar-imagen-en celda, ya que, que yo sepa, no hay forma de hacerlo desde código.
Pero si puedo utilizar la función "image(url;[])
Pero la url que nos da drive de una imagen, utilizando "conseguir enlace" no funciona con esta función.
Me funciona, sin embargo, la combinación de https://drive.google.com/uc?export=view&id= con el id de cada imagen.
Para hacerle la vida más fácil al usuario, le pido la url de "conseguir enlace" y mediante este trozo de código la convierto al tipo de enlace que he descrito en el anterior párrafo:
var herramienta = SpreadsheetApp.getActiveSpreadsheet()
var imagen_url = herramienta.getRangeByName('imagen').getValue()
var imagen_primera_parte = "https://drive.google.com/uc?export=view&id="
var imagen_id = imagen_url.match(/[-\w]{25,}/)
var imagen = imagen_primera_parte+imagen_id
pestana.getRange('A1').setValue('=image("'+imagen+'";1)')
El código funciona perfectamente: desde la url extrae el id de la imagen y después la añade al enlace especial. Con la última fila del código, insertamos la imagen en la celda A1 con la función image.
Pero, me he encontrado con la SORPRESA que hay veces que la imagen aparece y otras que no.
Después de investigar y probar diferentes situaciones, me he encontrado con que aparece siempre la imagen si utilizamos un proceso muy particular.
El proceso funciona así:
- Debemos subir la imagen desde el ordenador
- Debemos darle permiso público a la imagen(cualquiera con el enlace)
Sorprendentemente, no me ha funcionado con imágenes que ya estaban de antemano en mi Drive y, por supuesto, ninguna imagen que no tenga dado el permiso público de antemano.
lunes, 30 de noviembre de 2020
Regexmatch (Comportamiento extraño de la fórmula?!)
¡Cuidado con el orden de los datos en la fórmula!
El resultado no es el mismo
La formula regexmatch la traducimos así: Resultado de(texto donde se busca; texto a buscar)
Hay que tener claro que en la primera parte se define "donde" "dentro de"
Y en la segunda parte el "que"
Os planteo un caso real en la herramienta de reservas del aula de informática en un centro con horario tanto de mañana como de tarde. Esto es importante ya que las horas a reservar van desde las 8:30 a las 20:30
Vamos a ver si ( 18:30; todas las horas) nos da dos resultados: 8:30 y 18:30
En este busca cada hora del día si cabe en "18:30" y encuentra que tanto 8:30 como 18:30 caben
Pero, al revés, ( todas las horas; 18:30) nos da solamente 18:30
En este caso busca la hora 18:30 si cabe en alguna hora del día y solamente encuentra 18:30
En resumen:
El orden de los parámetros de la fórmula es al revés de como lo formulamos, primero en donde buscamos y, segundo el qué.
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...
-
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...
-
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 ...
-
Estoy haciendo código para conseguir quitar todos los permisos a un correo concreto en todos los archivos y subcarpetas de una carpeta dada....