Crear PDFs desde Google Sheets

Crear PDFs desde Google Sheets y Google Apps Script

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:

  1. Vamos a “Archivo” > “Descargar” > “PDF”
  2. 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:

  1. Conectarnos con el libro actual con SpreadsheetApp.getActiveSpreadsheet()
  2. Convertir el libro en un archivo blob con .getBlob()
  3. Crear el PDF a partir del blob con DriveApp.createFile(blob)
  4. 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:

  1. Conectarnos con el libro actual con SpreadsheetApp.getActiveSpreadsheet()
  2. Averiguamos la URL del libro con .getURL()
  3. Le quitamos al URL el texto “edit”
  4. Le agregamos a la URL, el texto “”export?exportFormat=pdf”
  5. Creamos el objeto “parametros”
  6. Creamos una respuesta HTML, llamando el método URLFetchApp.fetch() con la URL y los parámetros.
  7. Convertimos la respuesta en un blob con el método .getAs()
  8. 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

  1. Llamar a la hoja (En nuestro ejemplo va a ser la hoja activa)
  2. Traer la ID de la pestaña que queremos exportar
  3. 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:

  1. Llamamos el rango deseado, en nuestro caso va a ser el rango activo
  2. Extraemos la columna inicial y final, y la fila inicial y final del rango
  3. 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

33 comentarios en “Crear PDFs desde Google Sheets”

  1. Mauricio Martínez Valencia

    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.

    1. 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!

  2. 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,

    1. 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!

  3. 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

    1. 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!

  4. 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.

  5. 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.

    1. 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!

  6. 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!

  7. 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).

  8. 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.

  9. 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.

  10. 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.-

  11. 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!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Pin It on Pinterest

Share This