En este artículo vemos como generar PDFs a partir de nuestro libro, hojas y rangos de nuestra hoja de cálculo, tanto de manera manual, como de manera automática con código.
Qué es un PDF
PDF son las siglas de Printable Document Format, un formato de archivo que tiene dos importantes características
- Tal como lo imprimimos, lo va a ver nuestro destinatario o público.
- No se puede modificar.
Por qué exportar a PDF
PDF ha sido un formato muy utilizado en los últimos años debido a su facilidad de compartir, y a que todos los computadores, exploradores y dispositivos.
Por eso es mucho más fácil enviar un PDF que un Excel o un Sheets
Exportar PDFs manualmente desde Google Sheets
Sheets, como muchos otros programas, nos da la opción de exportar nuestros Sheets cómo PDFs
Esto lo podemos hacer de dos maneras:
- Vamos a «Archivo» > «Descargar» > «PDF»
- Vamos a «Archivo» > «Imprimir», y en «Siguiente», y en «Destino», seleccionamos «Guardar como PDF»
La diferencia entre los dos métodos es que al imprimir tenemos varias opciones de márgenes y ajuste, y así controlar un poco más la apariencia de nuestro PDF
Exportar PDFs con Google Apps Script
Tenemos varias maneras de crear PDFs desde Google Apps Script y Google Sheets
Entre otras podríamos hacer lo siguiente
- Crear un PDF de un libro
- Crear PDF de una hoja
- Crear PDF de un rango
- Crear PDF a partir de una fila y una plantilla (Docs, Slides, Html o Sheets)
Glosario
PDF: Formato de Archivo Imprimible
Blob: Archivo crudo que contiene un tamaño y un tipo
MimeType: El tipo de archivo del blob
«application/pdf»: El tipo de archivo de un pdf
Exportar el libro
Vamos a empezar con el método más sencillo: exportar un libro entero
Para esto debemos:
- Conectarnos con el libro actual con SpreadsheetApp.getActiveSpreadsheet()
- Convertir el libro en un archivo blob con .getBlob()
- Crear el PDF a partir del blob con DriveApp.createFile(blob)
- Darle un nombre con .setName(nombre)
//Conectar con el libro de Sheets
var libro = SpreadsheetApp.getActiveSpreadsheet()
//Crear el blob
var blob=libro.getBlob()
//Crear el pdf
DriveApp.createFile(blob).setName("PDF ahora si con formato")
Exportar PDF con más opciones de formato
La anterior es una manera muy válida de exportar pero es poco flexible porque no podemos controlar el aspecto de nuestro PDF
Hay una manera un poco más complicada pero mucho más robusta y profesional
Estos son los pasos:
- Conectarnos con el libro actual con SpreadsheetApp.getActiveSpreadsheet()
- Averiguamos la URL del libro con .getURL()
- Le quitamos al URL el texto «edit»
- Le agregamos a la URL, el texto «»export?exportFormat=pdf»
- Creamos el objeto «parametros»
- Creamos una respuesta HTML, llamando el método URLFetchApp.fetch() con la URL y los parámetros.
- Convertimos la respuesta en un blob con el método .getAs()
- Crear el PDF a partir del blob con DriveApp.createFile(blob)Darle un nombre con .setName(nombre)
function crearPDFPersonalizable() {
var libro = SpreadsheetApp.getActiveSpreadsheet();
var url = libro.getUrl()
var urlNuevo = url.replace("edit", "")
urlNuevo += "export?exportFormat=pdf"
var parametros = {
muteHttpExceptions: true,
headers: {
Authorization: 'Bearer ' + ScriptApp.getOAuthToken(),
}
}
var respuesta=UrlFetchApp.fetch(urlNuevo, parametros)
var blob=respuesta.getAs("application/pdf")
DriveApp.createFile(blob).setName("Nombre del PDF")
}
Insertar las opciones de Formato
Diras tu, pero que diferencia hay entre el primer método que vimos, y este mucho mas complicado, si el resultado es exactamente el mismo.
La diferencia radica en que podemos incluir opciones de parametrización y formato para nuestro HTML
Y lo único que debemos hacer es agregar a nuestra URL la opción que queremos modificar y el valor de la misma
Aquí les dejo el listado de todas las opciones.
Siéntete libre de agregar o eliminar el que necesites
function crearPDFPersonalizable() {
var libro = SpreadsheetApp.getActiveSpreadsheet();
var url = libro.getUrl()
var urlNuevo = url.replace("edit", "") +
"export?exportFormat=pdf"+
"&format=pdf"+ //Formato de exportación {pdf}
"&size=LETTER" + //Tamaño de Papel {LETTER=carta, LEGAL=oficio}
"&portrait=true" + //Orientación {true=vertical, false=horizontal}
"&fitw=false" + //Ajustar al ancho {true=ajusta, false=no ajusta}
"&scale=1" + //Ajustes {1=100%,2=Ancho,3=Alto,4=Página}
"&gridlines=false" + //Lineas de cuadrícula {true=se muestran. false=no}
"&fzr=true" + //Encabezados en todas las hojas {true=si, false=no}
"&fzc=false"+ //Primera columna en todas las hojas {true=si, false=no}
"&printtitle=true" + //Titulo en parte superior izq {true=si, false=no}
"&pagenum=CENTER" + //Numeración pie de página {CENTER=si, UNDEFINED =no}
"&sheetnames=true"+ //Nombre de la hoja superior derecha {true=si, false=no}
"&top_margin=0.7"+
"&bottom_margin=0.7"+
"&left_margin=1"+
"&right_margin=1" + //Unidades de margenes, acepta decimales {0 es nada, 2 es mucho}
"&horizontal_alignment=CENTER"+ //Alineación horizontal {LEFT,CENTER,RIGHT}
"&vertical_alignment=BOTTOM"+ //Alineación vertical {TOP,MIDDLE,BOTTOM}
"&printnotes=false" + //Imprimir notas {true=imprime (default), false=no imprime}
"&pageorder=1" + // Orden si se desborda la tabla {1=Abajo y despues derecha, 2=Al revés}
var parametros = {
muteHttpExceptions: true,
headers: {
Authorization: 'Bearer ' + ScriptApp.getOAuthToken(),
}
}
var respuesta=UrlFetchApp.fetch(urlNuevo, parametros)
var blob=respuesta.getAs("application/pdf")
DriveApp.createFile(blob).setName("Nombre del PDF")
}
Exportar una hoja de Google Sheets como PDF
Esta es una extensión del código anterior
Lo único adicional que debemos hacer es
- Llamar a la hoja (En nuestro ejemplo va a ser la hoja activa)
- Traer la ID de la pestaña que queremos exportar
- Agregar esa id a la url con el parametro «&gid=»
Esto sería lo que agregaríamos
var hoja=libro.getActiveSheet();
var idHoja=hoja.getSheetId();
urlNuevo += "export?exportFormat=pdf" + "&gid=" + idHoja
Quedaría así el código total
function crearPDFPersonalizable() {
var libro = SpreadsheetApp.getActiveSpreadsheet();
var url = libro.getUrl()
var hoja=libro.getActiveSheet();
var idHoja=hoja.getSheetId();
var urlNuevo = url.replace("edit", "") +
"export?exportFormat=pdf"+
"&format=pdf"+ //Formato de exportación {pdf}
"&size=LETTER" + //Tamaño de Papel {LETTER=carta, LEGAL=oficio}
"&portrait=true" + //Orientación {true=vertical, false=horizontal}
"&fitw=false" + //Ajustar al ancho {true=ajusta, false=no ajusta}
"&scale=1" + //Ajustes {1=100%,2=Ancho,3=Alto,4=Página}
"&gridlines=false" + //Lineas de cuadrícula {true=se muestran. false=no}
"&fzr=true" + //Encabezados en todas las hojas {true=si, false=no}
"&fzc=false"+ //Primera columna en todas las hojas {true=si, false=no}
"&printtitle=true" + //Titulo en parte superior izq {true=si, false=no}
"&pagenum=CENTER" + //Numeración pie de página {CENTER=si, UNDEFINED =no}
"&sheetnames=true"+ //Nombre de la hoja superior derecha {true=si, false=no}
"&top_margin=0.7"+
"&bottom_margin=0.7"+
"&left_margin=1"+
"&right_margin=1" + //Unidades de margenes, acepta decimales {0 es nada, 2 es mucho}
"&horizontal_alignment=CENTER"+ //Alineación horizontal {LEFT,CENTER,RIGHT}
"&vertical_alignment=BOTTOM"+ //Alineación vertical {TOP,MIDDLE,BOTTOM}
"&printnotes=false" + //Imprimir notas {true=imprime (default), false=no imprime}
"&pageorder=1" + // Orden si se desborda la tabla {1=Abajo y despues derecha, 2=Al revés}
urlNuevo += "export?exportFormat=pdf" + "&gid=" + idHoja
var parametros = {
muteHttpExceptions: true,
headers: {
Authorization: 'Bearer ' + ScriptApp.getOAuthToken(),
}
}
var respuesta=UrlFetchApp.fetch(urlNuevo, parametros)
var blob=respuesta.getAs("application/pdf")
DriveApp.createFile(blob).setName("Nombre del PDF")
}
Exportar un rango
Una última cosa que podemos agregar al código anterior es la habilidad de exportar un rango específico. Para esto debemos adicionar lo siguiente:
- Llamamos el rango deseado, en nuestro caso va a ser el rango activo
- Extraemos la columna inicial y final, y la fila inicial y final del rango
- Agregamos estos valores a nuestro url con los parámetros r1,r2,c1 y c2
Esto sería lo que agregaríamos:
var columnaInicial = rango.getColumn() - 1;
var filaInicial = rango.getRow() - 1;
var columnaFinal = rango.getLastColumn();
var filaFinal = rango.getLastRow();
urlNuevo += "&r1=" + filaInicial + //Fila de inicio (Ej: 0 es la fila 1)
"&r2=" + filaFinal + //Fila de fin (Ej: # de la fila final)
"&c1=" + columnaInicial + //Col de inicio (Ej: 0 es la columna A)
"&c2=" + columnaFinal // Col de fin (Ej: 2 es la columna B)
Así quedaría todo el código
function crearPDFPersonalizable() {
var libro = SpreadsheetApp.getActiveSpreadsheet(
var url = libro.getUrl()
var hoja=libro.getActiveSheet();
var idHoja=hoja.getSheetId();
var columnaInicial = rango.getColumn() - 1;
var filaInicial = rango.getRow() - 1;
var columnaFinal = rango.getLastColumn();
var filaFinal = rango.getLastRow();
var urlNuevo = url.replace("edit", "") +
"export?exportFormat=pdf"+
"&format=pdf"+ //Formato de exportación {pdf}
"&size=LETTER" + //Tamaño de Papel {LETTER=carta, LEGAL=oficio}
"&portrait=true" + //Orientación {true=vertical, false=horizontal}
"&fitw=false" + //Ajustar al ancho {true=ajusta, false=no ajusta}
"&scale=1" + //Ajustes {1=100%,2=Ancho,3=Alto,4=Página}
"&gridlines=false" + //Lineas de cuadrícula {true=se muestran. false=no}
"&fzr=true" + //Encabezados en todas las hojas {true=si, false=no}
"&fzc=false"+ //Primera columna en todas las hojas {true=si, false=no}
"&printtitle=true" + //Titulo en parte superior izq {true=si, false=no}
"&pagenum=CENTER" + //Numeración pie de página {CENTER=si, UNDEFINED =no}
"&sheetnames=true"+ //Nombre de la hoja superior derecha {true=si, false=no}
"&top_margin=0.7"+
"&bottom_margin=0.7"+
"&left_margin=1"+
"&right_margin=1" + //Unidades de margenes, acepta decimales {0 es nada, 2 es mucho}
"&horizontal_alignment=CENTER"+ //Alineación horizontal {LEFT,CENTER,RIGHT}
"&vertical_alignment=BOTTOM"+ //Alineación vertical {TOP,MIDDLE,BOTTOM}
"&printnotes=false" + //Imprimir notas {true=imprime (default), false=no imprime}
"&pageorder=1" + // Orden si se desborda la tabla {1=Abajo y despues derecha, 2=Al revés}
urlNuevo += "export?exportFormat=pdf" + "&gid=" + idHoja
urlNuevo += "&r1=" + filaInicial + //Fila de inicio (Ej: 0 es la fila 1)
"&r2=" + filaFinal + //Fila de fin (Ej: numero de la fila donde termina el rango)
"&c1=" + columnaInicial + //Columna de inicio (Ej: 0 es la columna A)
"&c2=" + columnaFinal // Columna de fin (Ej: 2 es la columna B)
var parametros = {
muteHttpExceptions: true,
headers: {
Authorization: 'Bearer ' + ScriptApp.getOAuthToken(),
}
}
var respuesta=UrlFetchApp.fetch(urlNuevo, parametros)
var blob=respuesta.getAs("application/pdf")
DriveApp.createFile(blob).setName("Nombre del PDF")
}
Conclusión
Como ves, no es tan difícil crear PDFs desde nuestros Sheets, con un poco de código
Y hasta ahora estamos tocando la punta del iceberg, porque hay muchas más cosas que podemos hacer con nuestras tablas para hacer informes automatizados en PDF
Hola, gracias por compartir estos artículos muy importantes, mi pregunta es la siguiente para el tema de «Exportar un rango» en la opción de tamaña de hoja, como podría hacer si es un tamaño personalizado. Gracias
Hola!
Cambias estas variables por tus números
var columnaInicial = rango.getColumn() – 1;
var filaInicial = rango.getRow() – 1;
var columnaFinal = rango.getLastColumn();
var filaFinal = rango.getLastRow();
Nos podemos poner más creativos y por ejemplo seleccionar un rango, me imagino que a eso te refieres?
Saludos!
Hola, gracias por toda esta información, me pregunto si sera posible que el PDF se genere protegido con una contraseña ?
Hmmmm
Buena pregunta!
En principio te diría que no
Pero voy a investigar
Saludos!
Buen día Juan, tu contenido me ha ayudado mucho; tengo un emprendimiento de venta de grasas y aceites y estoy intentando crear todo el sistema en google sheets; pero tengo dos dificultades; la primera es que quiero enviar como adjunto una hoja de un libro con la siguiente función, pero me trae todo el libro y no he conseguido que solo traiga la hoja que quiero traer porque me arroja un error:
var pdf= SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
// Obtener la dirección de correo electrónico desde la celda A2
const destinatario = sheet.getRange(«C53»).getValue();
// Obtener el asunto del correo desde la celda B2
const asunto = sheet.getRange(«C54»).getValue();
// Obtener el mensaje del correo desde la celda C2
const mensaje = sheet.getRange(«C55»).getValue();
MailApp.sendEmail(destinatario, asunto, mensaje, {
attachments: [pdf.getAs(MimeType.PDF)]
});
La segunda es que cree un sistema para guardar remisiones, pero el tema es que luego requiero actualizarlas y no he conseguido hacer un código que me permita actualizar una base de datos existente desde un formato creado en otra hoja del mismo libro.
Hola!
PAra hacer una sola hoja, una opción fácil e ocultar todas las demas hojas en el momento que vayas a hacer la exportación
Esto lo puedes hacer manual o con un código
La otra opción es generar el PDF con el fetchApp que explico en el artículo y le especificas el id de tu hoja
Saludos!
Buenos días, y si en lugar de una hoja, son varias las que tengo que unir en un solo PDF? No puedo ocultar el resto de las hojas porque están protegidas.
Muchas gracias por adelantado y un saludo
Hola!
Interesante!
No se si se pueda sin recurrir a alguna otra aplicación
Lo investigo
Saludos!
Buenos días,
Tengo una pregunta. He hecho un documento sheets que tiene varias hojas, pues son unos informes. Tengo creada una macro para que los informes queden protegidos y que solo se puedan editar ciertas celdas. Ahora quería descargarlos a PDF por separado y con el nombre de cada hoja a una carpeta específica de drive.
¿Me puede ayudar? He copiado una de estas opciones que comentas, pero me descara todo el libro y me salen las cuadrículas.
Muchas gracias de antemano.
Un saludo,
Hola!
Prueba con este
function exportarHojasAPDF() {
var carpetaDestino = DriveApp.getFolderById(«11ExnWcXgi0u87bMpAz6bwzFM8DNw7D0V»); // Reemplaza «ID de la carpeta
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
sheets.forEach(sheet => sheet.showSheet())
for (var i = 0; i < sheets.length; i++) { var nombre = sheets[i].getName(); sheets.forEach(function (sheet) { if (sheet.getName() !== nombre) { sheet.hideSheet(); } else { sheet.showSheet(); } }); var blob = ss.getBlob().getAs('application/pdf').setName(nombre + ".pdf"); carpetaDestino.createFile(blob); sheets.forEach(sheet => sheet.showSheet())
}
}
Saludos!
A mi me ha funcionado esta solución para generar las hojas por separado, ya que la propuesta en la teoría me da problemas al declarar la variable urlNuevo que no he sabido solventar.
Muchisimas gracias
Hola que tal, saludos desde chile.
estoy creando un crm y una parte es crear las cotizaciones, tengo dos problemitas con esto,.
1. quiero solo guardar la hoja de la cotizacion (ya lo logre pero no me guarda la imagen del logo de la empresa) hay alguna solucionpara esto? como puedo hacer que me «imprima el logo».
2. la cotizacion esta compuesta de una portada, la cotizacion y condiciones de servicio (hojas separadas) intenter hacer un for y ocultar hojas pero solo me reconoce la primera. existira alguna otra forma?
saludos y quedo atento
Hola!
Para haer los PDFs separados usa este código
function exportarHojasAPDF() {
var carpetaDestino = DriveApp.getFolderById(«11ExnWcXgi0u87bMpAz6bwzFM8DNw7D0V»); // Reemplaza «ID de la carpeta
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
sheets.forEach(sheet => sheet.showSheet())
for (var i = 0; i sheet.showSheet())
}
}
Saludos!
Hola amigo, muchas gracias por tu excelente post. copio todo el codigo de la parte de exportar un rango pero me arroja el siguiente error: «Error de sintaxis: SyntaxError: Invalid left-hand side in assignment, línea: 236, archivo: macros.gs»; se refiere a la entrada de la funcion: «var urlNuevo = url.replace(«edit», «») +».
De antemano Gracias.
Este error puede pasar si ya habías definido la variable usando la palabra var antes
Saludos!
Hola Juan porque cuando exporto el sheet con imágenes, estás no aparecen en el pdf?
HOla Daniel
Las imagenes no son parte del documento, sino que son adiciones
Por eso no te salen
Saludos!
Excelente, me sirvio demasiado, utilice el primer codigo y oculte las otras hojas
Hola
Excelente! Me alegra ser de utilidad.
Un gran saludo!
Buenas, muchos consejo me han servido para ir mejorando los trabajos que hago con google sheets, soy docente de escuela técnica, encargado de la comunicación por web para las familias y directivo.
La consulta es la siguiente:
En una celda A1 pego ‘https://docs.google.com/spreadsheets/…’ y en A2’=A1&»pub?output=pdf»‘
Por lo tanto creo el siguiente vínculo en A2 ‘https://docs.google.com/spreadsheets/d/e/xxxxx/pub?output=pdf’
El mismo me imprime en un formato único y deseo cambiarlo, a ajuste a hoja y letter, podría darme una ayuda.
Desde ya muchas y saludos desde Argentina.
Hola!
De pronto hay una opción para que despues del output=pdf pongas los demas parametros como lo explico en el articulo
Intenta por ejemplo poner
A1&»pub?output=pdf&size=LETTER»
a ver que pasa
Saludos!
hola juan! me encanta tu contenido y es de excelente calidad, me gustaria saber como hago para exportar a pdf con appscript 2 hojas de una hoja de calculo suponiendo que esta tiene mas de 3. desde ya muchas gracias!
Hola!
Debes hacer un código que va hoja por hoja y oculta las que no son
El código de script con el libro te publica todas las hojas MOSTRADAS
Saludos!
Estimado Juan, Muchas gracias por el aporte. Sería posible insertar la fecha en el que creamos el PDF en el encabezado o pie de página, al igual que insertamos el título del libro (printtitle) o el número de páginas (pagenum).
Hola Juan, te hago una consulta.
Por qué me arroja este error al tratar de ejecutar el código?
Error de sintaxis: SyntaxError: Invalid left-hand side in assignment, línea: 9, archivo: Código.gs
He revisado bastante pero no comprendo que puede causar el error. Espero puedas ayudarme amigo. Saludos.
Hola!
Normalmente puede ser que estas tratando de poner algo a una constante
Saludos!
No se pudo abrir el archivo en este momento.
Verifica la dirección e inténtalo de nuevo.
buen día, al realizar el codigo de pdf especifico me sale este mensaje en el pdf y no las hojas del Sheet, como lo soluciono
Realiza tus proyectos con Google Drive
Las aplicaciones de Google Drive te facilitan la
tarea de crear, almacenar y compartir documentos,
hojas de cálculo, presentaciones y otros archivos
en línea.
Obtén más información en
drive.google.com/start/apps.
ASegurate que el código este exacto, particularmente la parte del urlfetch
Saludos!
Hola Juan! Tengo una consulta, al momento de ponerle el formato copiando el código de esta página no me lo cambia. Entiendo que el problema esta en la Url Nuevo pero no logro identificar cual es el error.
Muchas gracias.
Saludos.-
Hola Luciana
Disculpa la demora
Espero hayas logrado solucionar
Saludos!
Se podría hacer un link de descarga directa? Qué le pique y se descargue en pdf
Hmmm
No creo que se pueda, pero me equivocado en el pasado
Saludos!
¡Hola! ¿Es posible que el nombre del pdf incluya un número que está en una celda del mismo Sheets? No lo he podido lograr
Hola!
Claro que si
En setName incluyes la variable que se refiere a la celda que quieres
Saludos!
Hola Juan G.
Muchas gracias por la info bastante detallada en tu explicación.
Muy buen aporte de 5 estrellas.
Gracias por el comentario!
Hola, Juan
Es posible crear un pdf de varias páginas a partir de una hoja, como cuando exportas en pdf con áreas de impresión.
Muchas gracias
Hola Rebeca
Prueba imprimiendo un pdf manualmente y estableciendo los saltos de página ahi, y despues si ejecutas el código a ver como te va
Saludos
Hola Juan. Te hago una consulta, en cuanto a las opciones de tamaño de hoja, solo es posible Letter y Legal? Porque nosotros usamos el 100% en formato A4. No hay opción?? Gracias desde ya, y sos un genio hermano!
HOla, creo que A4 tambien la acepta. Ya probaste?
Mil gracias por tus palabras!
Saludos!