Exportando datos de tablas HTML a CSV y formato de hoja de cálculo: programación del snippet en lenguaje Javascript en versiones con y sin JQuery...

in #spanish6 years ago (edited)
Formatos de archivos


Con frecuencia, los usuarios de páginas web tienen la necesidad de exportar algunos datos del contenido que visita, a fin de almacenarlos como archivos en medios locales o cuentas de almacenamiento online, y reutilizarlos posteriormente de diversas maneras. Un ejemplo simple de exportación se consigue fácilmente en Wikipedia, cuando nos ofrece la posibilidad de descargar el contenido en formato PDF. También, el descargar un vídeo de YouTube frecuentemente conlleva con un proceso de exportación.

No obstante, en ocasiones no resulta suficientemente conveniente el descargar una página web completa o sólo su contenido html, puesto que posiblemente estemos interesados en algunos datos en específico. Un ejemplo de ello se visualiza en la tabla 1. Se trata de los datos de los movimientos bancarios o el estado de cuenta que refleja el sistema de banca electrónica. (véase tabla 1)

Tabla 1: Movimientos bancarios

Fecha de transacción Fecha efectiva Referencia Descripción Monto
23/03/2018 23/03/2018 0385990177 COMPRA POS -102.000,00
27/03/2018 27/03/2018 0008063859 RETIRO POR TAQUILLA -50.000,00
28/03/2018 28/03/2018 0000000000 INTERESES 3.043,08

Esto muestra que no nos interesa almacenar toda la página, sólo esos datos en específico. Dependerá de las funciones del sitio web, por tanto, la posibilidad de ofrecer alguna manera de exportar datos.

En este post se hará una demostración de cómo programar esta función de exportación de datos contenidos en una tabla (table) en HTML a formato de txt (texto plano), formato CSV (comma separated values) y formato xlsx, (nativo de Microsoft Excel), ya que este último es un estándar de facto mundialmente utilizado.

Se programará del lado del cliente, es decir, usando Javascript, no requeriendo así de tener que programarlo en el lado del servidor. Se diseñará primero un snippet con una solución básica que prescinde de toda librería. A continuación parte del archivo index.php:

<table id="tabla_datos" >
 <thead>      <th>Fecha de transacción</th>      <th>Fecha efectiva</th>      <th>Referencia</th>      <th>Descripción</th>      <th>Monto</th>    </tr>  </thead>  <tbody>  <?php    //Hacemos la consulta a la DB:    $sql = "SELECT FechaTransaccion, FechaEfectiva,"    $sql .= " FechaTransaccion, FechaEfectiva,";    $sql .= " Descripcion, Monto";    $sql .= " FROM Movimientos LIMIT 20";    $res = mysqli_query($conexion, $sql) or die("Error de DB:". mysqli_error($conexion));    while($reg = mysqli_fetch_assoc($res)) {        //Rellenamos las celdas de la tabla:  ?>    <tr>      <td><?php echo $reg['FechaTransaccion'];?></td>      <td><?php echo $reg['FechaEfectiva'];?></td>      <td><?php echo $reg['Referencia'];?></td>      <td><?php echo $reg['Descripcion'];?></td>      <td><?php echo $reg['Monto'];?></td>    </tr>  <?php } ?>  </tbody> </table>


Esta porción de código contruye una tabla de HTML utilizando los registros de una tabla de base de datos llamada "Movimientos", que bien podría haberse creado con una sentencia SQL como la siguiente: 

CREATE TABLE Movimientos (
Id int NOT NULL,
FechaTransaccion date NOT NULL,
FechaEfectiva date NOT NULL,
Referencia int NOT NULL,
Descripcion varchar(255) NOT NULL,
Monto double NOT NULL)


Ahora bien, nótese que en el index.php se han usado las etiquetas que distinguen la cabecera (thead) de la tabla de su cuerpo (tbody), lo cual le da más semántica a los datos contenidos. Ahora debemos añadir alguna función que dispare el proceso de exportación y descarga. En este caso se añadirá un botón (button) como sigue:

<?php //Insertamos un botón para la descarga: ?>
<input type="button" class="exportar" value="exportar" id="exportar">


 Ahora se importa el código javascript al documento HTML:

<?php //Insertamos el código javascript que hace el trabajo: ?>
<script type="text/javascript" src="exportacion.js"></script>


Se ha importado un archivo exportacion.js que contiene el snippet con la solución personalizada para este problema, prescindiendo de toda librería externa. Dicho código se muestra y explica a continuación:

/* Esta función extrae el contenido de las celdas y crea un<
 * objeto Array con ella, para luego enviárselas a
 * 'exportToCsv'.
 */
function exportToCsv(nombreArchivo, filas) {
  var processRow = function (row) {
    var valorFinal = "";
    for (var j = 0; j < row.length; j++) {
      var valorInner = row[j] === null ? "" : row[j].toString();
      if (row[j] instanceof Date) {
        valorInner = row[j].toLocaleString();
      };
      var result = valorInner.replace(/"/g, '""');
      if (result.search(/("|,|\n)/g) >= 0)
        result = '"' + result + '"';
      if (j > 0)
        valorFinal += ',';
      valorFinal += result;
    }
    return valorFinal + '\n';
  };
  var archivoCsv = '';
  for (var i = 0; i < filas.length; i++) {
    archivoCsv += processRow(filas[i]);
  }
  var blob = new Blob([archivoCsv], { type: 'text/csv;charset=utf-8;' });
  if (navigator.msSaveBlob) { // IE 10+
    navigator.msSaveBlob(blob, nombreArchivo);
  } 
  else {
    var link = document.createElement("a");
    if (link.download !== undefined) {
      // Navegadores que soportan el atributo de descarga de HTML5
      var url = URL.createObjectURL(blob);
      link.setAttribute("href", url);
      link.setAttribute("download", nombreArchivo);
      link.style.visibility = 'hidden';
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    }
  }
}
/* Esta función extrae el contenido de las celdas y crea un
 * objeto Array con ella, para luego enviárselas a
 * 'exportToCsv'.
 */
function exportarACSV(){
  alert("en exportar")
  arreglo = Array()
  table = document.getElementById('tabla_datos')
  for (var i=0;i < table.rows.length; i++){
    afilas = Array()
    nceldas = table.rows[i].getElementsByTagName("th")
    for (var j=0; j<nceldas.length; j++){
      afilas.push(nceldas[j].innerHTML)
    }
    nceldas = table.rows[i].getElementsByTagName("td")
    for (var j=0; j<nceldas.length; j++){
      afilas.push(nceldas[j].innerHTML)
    }
    arreglo.push(afilas)
  }
  alert(arreglo);
  resp = exportToCsv("archivo.csv", arreglo)
}
//Asignamos una manejador del evento click al botón html:
document.getElementById('exportar').addEventListener('click',exportarACSV, false);


El snippet posee un par de funciones con nombres similares, pero como bien explican los comentarios, la primera función llamada exportarACSV se limita a extraer el contenido de la tabla HTML y representarlo como un Array de Array (una matriz). Luego se llama a la función exportToCsv que toma como entrada una matriz de elementos y agrega un elemento al DOM para implementar la descarga del archivo con la información de la tabla en formato CSV, el cual es también interpretable por software de hojas de cálculo como Excel o Calc.

Otra solución involucra el uso de librerías de terceros tales como el plugin tableExport que funciona con librería JQuery. Para implementar esto, simplemente hay que sustituir los scripts de javascript importados previamente por estos:

<script src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script src='tableExport/tableExport.js'></script>
<script type='text/javascript' src='tableExport/jquery.base64.js'></script>
<script src='js/exportacion2.js'></script>


Y el script contenido en exportación2.js correspondería con este:

//Usando JQuery para solucionar la exportación:
$( document ).ready(function() {
  $(".exportar").click(function() {
    var export_type = $(this).data('export-type');
    $('#tabla_datos').tableExport();
  });
});


Y con esto conseguimos los resultados esperados. Además de la reducción de código, tableExport también simplifica el trabajo con varias otras opciones tales como: incluir encabezados (headers), incluir pies de página (footers), especificar el formato de salida (no sólo CSV, sino txt y xlsx) y otras. Su documentación oficial se consigue en las referencias.

A continuación se muestra una ejemplo del proceso de descarga con las soluciones implementadas (véase imágenes 1 y 2).

Vista de navegador con tabla HTML con datos de movimientos bancarios y un cuadro de descarga de archivo

Imagen 1: Captura de pantalla como demostración del funcionamiento del script. Fuente: el autor. Licencia: dominio público.

Ventana de LibreOffice Calc

Imagen 2: Captura de pantalla del archivo descargado y abierto con un programa de hoja de cálculo (Calc). Fuente: el autor. Licencia: dominio público.


REFERENCIAS:

-Entrada "How to export JavaScript array info to csv" disponible en StackOverFlow.com

-Repositorio en GitHub.com de la librería TableExport

Nota: la imagen de portada es de MTZD y es de licencia: dominio público. Todo el código que he programado y publicado aquí debe ser considerado de dominio público



Sort:  

Usted ha recibido un upvote por la comunidad @inteligentzia y su TRAIL de curadores ya que consideramos su post de información útil y de relevancia creativa.

Si quieres saber mas del proyecto aqui te dejamos nuestro post introductorio

Tambien puedes unirte a nuestro canales en el Chat Discord o en nuestro Grupo de Facebook para saber mas del proyecto!

Muchas gracias!

We have face major hacking attack on our server and we think your account might be in risk. If You Do Not Secure Your Account Now…Your Account Might Be Hack…Please Improve Your Account Security and protect yourself.
Secure Your Account Click Here

Congratulations @eniolw! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of upvotes

Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

Upvote this notification to help all Steemit users. Learn why here!

Coin Marketplace

STEEM 0.19
TRX 0.15
JST 0.029
BTC 63407.49
ETH 2645.11
USDT 1.00
SBD 2.81