El lenguaje de marcado HTML es fundamental para el desarrollo web. Este juega un papel crucial en la gestión de elementos dentro de una página, así como en su modelado. HTML proporciona una estructura y sintaxis estandarizadas para crear páginas web, permitiendo a diseñadores y desarrolladores definir la estructura, contenido y diseño de un sitio de manera organizada y semántica. Entre los elementos más utilizados y versátiles dentro de un documento HTML se encuentran las tablas HTML.

Tablas HTML: Herramienta Versátil para Visualizar Datos

Las tablas HTML permiten organizar y visualizar datos de forma tabular, haciendo más clara y comprensible la presentación de la información. Una tabla en HTML puede ser utilizada para una amplia gama de propósitos, desde mostrar datos financieros complejos hasta crear calendarios o programas, proporcionando una estructura visual que facilita la comprensión y análisis de los datos.

La Necesidad de Convertir Tablas HTML a PDF

Existen situaciones en las que podrías querer convertir estas tablas a un formato diferente, como PDF, para compartir, archivar o simplemente imprimir.

No es raro encontrar aplicaciones web que contienen tablas HTML, gráficos y diagramas y que incluyen una opción para exportar los datos en formato PDF. Pero ¿cómo obtener un PDF con un aspecto profesional? La mayoría de los convertidores PDF en línea gratuitos simplemente convierten el contenido de una página HTML en un PDF sin aplicar ninguna formateo adicional, lo que puede dificultar la lectura de los datos. Sería conveniente agregar encabezados, índices, títulos a las tablas y un formato más cuidado de los datos, ¿no crees?

Veamos juntos qué herramientas lo permiten.

Herramientas para Obtener un PDF Profesional a partir de una Tabla en HTML

Convertir tablas HTML en PDF usando las herramientas integradas del navegador

En primer lugar, consideremos la posibilidad de exportar el PDF utilizando las herramientas integradas del navegador. Cuando visualizas una página web, puedes imprimir fácilmente haciendo clic con el botón derecho del ratón en cualquier lugar y eligiendo la opción de “Imprimir” en el menú. Esto abrirá una ventana de diálogo que te permitirá elegir las configuraciones de impresión.

Sin embargo, no es necesario imprimir el documento. La ventana de diálogo también ofrece la posibilidad de guardar el documento en formato PDF, lo cual haremos. En JavaScript, el objeto window tiene un método de impresión, por lo que podemos escribir una función JavaScript simple y vincularla a uno de nuestros botones de esta manera:

JavaScript
function descargarPDFConImpresionDelNavegador() {
  window.print();
}
document.querySelector('#imprimirNavegador').addEventListener('click', descargarPDFConImpresionDelNavegador);

El html correspondiente a exportar, en este caso, sería:

HTML
<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Descargar PDF con Impresión del Navegador</title>
</head>
<body>
  <p>Un post de htmldesdecero.es</p>
  <!-- Contenido de la página -->
  
  <button id="imprimirNavegador">Descargar PDF</button>

  <!-- Inclusión del script JavaScript -->
  <script>
    function descargarPDFConImpresionDelNavegador() {
      window.print();
    }

    document.querySelector('#imprimirNavegador').addEventListener('click', descargarPDFConImpresionDelNavegador);
  </script>
</body>
</html>
Exportar tabla de HTML a PDF con herramienta de navegador
Exportar tabla de HTML a PDF con herramienta de navegador y JS

El resultado obtenido es legible y bastante claro. Aunque no está personalizado, los aspectos principales de las tablas se han mantenido intactos. Además, cada una de las páginas incluye los encabezados de las columnas de la tabla y el pie de página, que el navegador ha detectado inteligentemente gracias a la elección de usar HTML semántico para construir una tabla correctamente estructurada.

See the Pen HTML-PDF-Navegador by Alex (@htmldesdecero) on CodePen.

Sin embargo, se incluyen metadatos adicionales de la página que el navegador agrega al PDF. En la parte superior, vemos la fecha y el título de la página HTML. Al final de la página está el sitio web del cual se imprimió el documento y el número de página. Si queremos un resultado que contenga los datos principales de la tabla, con el único propósito de ver los datos, Chrome hace un buen trabajo.

Otra cosa a tener en cuenta es que la funcionalidad de impresión nativa del navegador difiere de un navegador a otro. Por lo tanto, tendremos algunas diferencias mínimas según el navegador que usemos. Estas diferencias pueden mejorar o empeorar el resultado final.

Las tablas HTML se pueden exportar mediante herramientas externas al navegador de referencia. ¡Veamos algunas de ellas!

La librería jsPDF

Consideremos una librería de código abierto llamada jsPDF. Esta librería existe desde hace al menos varios años y se descarga más de 200,000 veces cada semana. Es una librería muy popular para manejar tablas en HTML.

jsPDF también es bastante fácil de usar. Se crea una nueva instancia de la clase jsPDF, se le proporciona una referencia al contenido HTML (considerando la existencia del tag de tabla HTML, es decir, <TABLE>) que se desea exportar y se proporcionan otras configuraciones, como el tamaño de los bordes de la tabla HTML o el título del documento.

JavaScript
  function downloadPDFWithjsPDF() {
    let doc = new jspdf.jsPDF('p', 'pt', 'a4');

    doc.html(document.querySelector('#styledTable'), {
      callback: function (doc) {
        doc.save('tabla.pdf');
      },
      margin: [60, 60, 60, 60],
      x: 32,
      y: 32,
    });
  }

  document.querySelector('#jsPDF').addEventListener('click', downloadPDFWithjsPDF);

El HTML correspondiente en este caso sería:

HTML
<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Descargar PDF con jsPDF</title>

  <!-- Incluir el archivo jsPDF -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js" integrity="sha512-qZvrmS2ekKPF2mSznTQsxqPgnpkI4DNTlrdUmTzrDgektczlKNRRhy5X5AAOnx5S09ydFYWWNSfcEqDTTHgtNA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js" integrity="sha512-BNaRQnYJYiPSqHHDb58B0yaPfCu+Wgds8Gp/gU33kqBtgNS4tSPHuGibyoeqMV/TJlSKda6FXzoEyYGjTe+vXA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>

  <!-- Contenido de la página -->

  <table id="styledTable">
    <!-- Inserta aquí tu contenido tabular -->
    <tr>
      <td>Contenido</td>
      <td>Contenido</td>
      <!-- Agrega más columnas o filas según sea necesario -->
    </tr>
  </table>

  <button id="jsPDF">Descargar PDF</button>

  <!-- Inclusión del script JavaScript -->
  <script>
  function downloadPDFWithjsPDF() {
    let doc = new jspdf.jsPDF('p', 'pt', 'a4');

    doc.html(document.querySelector('#styledTable'), {
      callback: function (doc) {
        doc.save('tabla.pdf'); // Cambiado el nombre del archivo PDF
      },
      margin: [60, 60, 60, 60],
      x: 32,
      y: 32,
    });
  }

  document.querySelector('#jsPDF').addEventListener('click', downloadPDFWithjsPDF);
  </script>
</body>
</html>

Dentro de sus procesos, jsPDF utiliza una librería llamada html2canvas. Como sugiere el nombre, html2canvas toma el contenido HTML y lo convierte en una imagen almacenada en un elemento HTML <canvas>. Luego, jsPDF toma el contenido del canvas y lo guarda.

El PDF obtenido incluye encabezados agradables y el fondo a rayas de las tablas, siendo muy comprensible. No contiene ninguno de los metadatos de página extra incluidos en el método de impresión del navegador.

Aunque jsPDF es una librería potente, parece que esta herramienta puede funcionar mejor cuando el contenido exportado cabe en una sola página. En tablas muy grandes en términos de longitud, la salida no es completamente comprensible o profesional, ya que es posible que el contenido se corte entre páginas o la falta de margen no nos permite obtener el contenido de texto íntegro (legible) en el PDF.

See the Pen Untitled by Alex (@htmldesdecero) on CodePen.

La librería Pdfmake

Pdfmake es una excelente elección para manejar tablas HTML. Es importante destacar que configurar pdfmake es mucho más complejo que jsPDF. La razón es que pdfmake construye el documento PDF desde cero utilizando los datos proporcionados por el usuario en lugar de convertir el contenido HTML existente en la página a PDF. Esto significa que en lugar de proporcionar una referencia a nuestra tabla HTML a pdfmake, debemos proporcionarle los datos para el encabezado, pie de página, contenido y diseño de nuestra tabla PDF.

El resultado que obtenemos es definitivamente superior a los documentos PDF vistos anteriormente. Podemos incluir estilos para nuestra tabla para reproducir los encabezados de columnas y fondos de fila. Además, los encabezados de columna de la tabla se repiten para facilitar el seguimiento de los datos mostrados en cada columna en cada página.

pdfmake nos permite incluir un encabezado y un pie de página, lo que nos permite agregar números de página.

Tabla HTML a PDF con pdfMake
Tabla HTML a PDF con pdfMake

En general, parece que el punto fuerte de pdfmake es la construcción de PDF desde cero. Por ejemplo, si deseamos generar una factura basada en los datos de un pedido y no queremos mostrar la factura en la pantalla de nuestra aplicación web, entonces pdfmake sería una excelente opción. A continuación, se muestra el código de referencia:

JavaScript
    function descargarPDFConPdfmake() {
      let cabeceraTabla = [...document.querySelectorAll('#styledTable thead tr th')].map(thElemento => ({ text: thElemento.textContent, style: 'encabezadoTabla' }));

      let celdasFilaTabla = [...document.querySelectorAll('#styledTable tbody tr td')].map(tdElemento => ({ text: tdElemento.textContent, style: 'datosTabla' }));
      let datosTablaComoFilas = celdasFilaTabla.reduce((filas, datosCelda, indice) => {
        if (indice % 4 === 0) {
          filas.push([]);
        }

        filas[filas.length - 1].push(datosCelda);
        return filas;
      }, []);

      let definicionDocumento = {
        header: { text: 'Ganadores de la Serie Mundial de la MLB', alignment: 'center' },
        footer: function(paginaActual, totalPaginas) { return ({ text: `Página ${paginaActual} de ${totalPaginas}`, alignment: 'center' }); },
        content: [
          {
            style: 'ejemploTabla',
            table: {
              headerRows: 1,
              body: [
                cabeceraTabla,
                ...datosTablaComoFilas,
              ]
            },
            layout: {
              fillColor: function(indiceFila) {
                if (indiceFila === 0) {
                  return '#0f4871';
                }
                return (indiceFila % 2 === 0) ? '#f2f2f2' : null;
              }
            },
          },
        ],
        styles: {
          ejemploTabla: {
            margin: [0, 20, 0, 80],
          },
          encabezadoTabla: {
            margin: 12,
            color: 'white',
          },
          datosTabla: {
            margin: 12,
          },
        },
      };
      pdfMake.createPdf(definicionDocumento).download('Ganadores de la Serie Mundial de la MLB');
    }

    document.querySelector('#pdfmake').addEventListener('click', descargarPDFConPdfmake);

El respectivo código HTML:

HTML
<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Descargar PDF con Pdfmake</title>

  <!-- Incluir el archivo Pdfmake -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.10/pdfmake.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.10/vfs_fonts.js"></script>
</head>
<body>

  <!-- Contenido de la página -->

  <table id="styledTable">
    <!-- Insertar aquí tu contenido tabular -->
    <thead>
    <tr>
        <th>Encabezado 1</th>
        <th>Encabezado 2</th>
        <!-- Agregar más columnas según sea necesario -->
    </tr>
    </thead>
    <tbody>
    <tr>
        <td>Dato 1</td>
        <td>Dato 2</td>
        <!-- Agregar más columnas según sea necesario -->
    </tr>
    <!-- Agregar más filas según sea necesario -->
    </tbody>
  </table>

  <button id="pdfmake">Descargar PDF</button>

  <!-- Inclusión del script JavaScript -->
  <script>
    function descargarPDFConPdfmake() {
      let cabeceraTabla = [...document.querySelectorAll('#styledTable thead tr th')].map(thElemento => ({ text: thElemento.textContent, style: 'encabezadoTabla' }));

      let celdasFilaTabla = [...document.querySelectorAll('#styledTable tbody tr td')].map(tdElemento => ({ text: tdElemento.textContent, style: 'datosTabla' }));
      let datosTablaComoFilas = celdasFilaTabla.reduce((filas, datosCelda, indice) => {
        if (indice % 4 === 0) {
          filas.push([]);
        }

        filas[filas.length - 1].push(datosCelda);
        return filas;
      }, []);

      let definicionDocumento = {
        header: { text: 'Ganadores de la Serie Mundial de la MLB', alignment: 'center' },
        footer: function(paginaActual, totalPaginas) { return ({ text: `Página ${paginaActual} de ${totalPaginas}`, alignment: 'center' }); },
        content: [
          {
            style: 'ejemploTabla',
            table: {
              headerRows: 1,
              body: [
                cabeceraTabla,
                ...datosTablaComoFilas,
              ]
            },
            layout: {
              fillColor: function(indiceFila) {
                if (indiceFila === 0) {
                  return '#0f4871';
                }
                return (indiceFila % 2 === 0) ? '#f2f2f2' : null;
              }
            },
          },
        ],
        styles: {
          ejemploTabla: {
            margin: [0, 20, 0, 80],
          },
          encabezadoTabla: {
            margin: 12,
            color: 'white',
          },
          datosTabla: {
            margin: 12,
          },
        },
      };
      pdfMake.createPdf(definicionDocumento).download('Ganadores de la Serie Mundial de la MLB');
    }

    document.querySelector('#pdfmake').addEventListener('click', descargarPDFConPdfmake);
  </script>
</body>
</html>

Aquí lo tienes en la versión CodePen:

See the Pen HTML-PDF-Pdfmake by Alex (@htmldesdecero) on CodePen.

En conclusión, pdfmake ofrece un resultado más profesional en todos los aspectos y proporciona muchas opciones de personalización. Sin embargo, requiere tiempo para interactuar y configurar esta librería, ya que no es tan intuitiva como la interacción con el navegador, pero optimiza la calidad de nuestro documento PDF que contiene la tabla HTML.

Califica este post