Totalize values from javascript columns

1

Good day  I have the following code that creates a dynamic table from an array.

var data = [
  {id:1, land: 'FINCA1',  product: "ROSA", week:25,  quantity: 2000}, 
  {id:1, land: 'FINCA2',  product: "ROSA", week:25, quantity: 1900}, 
  {id:1, land: 'FINCA3',  product: "ROSA", week:25, quantity: 350},
  {id:1, land: 'FINCA3',  product: "ROSA1",week:25, quantity: 410},
  {id:1, land: 'FINCA1',  product: "ROSA", week:26, quantity: 1254},
  {id:1, land: 'FINCA2' ,  product: "ROSA",week:26, quantity: 123},
  {id:1, land: 'FINCA3' ,  product: "ROSA",week:26, quantity: 200}
];

//Obtengo los keys del objeto para crear el Thead de la tabla y los guardo en una variable

var tabla = '';
var tableHead = '<tr>';

Object.keys(data[0]).forEach(function(prop){
  if(prop != 'week' && prop != 'quantity')
  tableHead += '<th>'+prop+'</th>';
});

var semanas = [];
    for(var i in data){
      semanas.push(
              data[i].week
      );
    }

    semanas = array_unique(semanas);
    var index = semanas.indexOf(undefined);
    if (index > -1) {
      semanas.splice(index, 1);
    }

    for(var a in semanas){
      tableHead += '<th style="text-align:right;">'+'Sem '+semanas[a]+'</th>';
    }

tableHead += '<th>Total</th>';


var arrayOrganizado = data.reduce(function(arr, item){
  item.week = {
    numero : item.week,
    cantidad : item.quantity
  }
  var ele = arr.find(it=>it.land === item.land && it.product === item.product);
  if(ele){
    ele.week.push(item.week);
    ele.total = ele.week.reduce((a, b)=> a + b.cantidad, 0);
  } else {
    item.week = [item.week];
    item.total = item.quantity;
    arr.push(item);
  }
  return arr;
}, []);

arrayOrganizado.forEach(function(fila){
 table += '<tr>';
  var f = Object.keys(fila).reduce( function(a, b){
    if(b != 'week' && b != 'quantity' && b != 'total')
      return a +  '<td>' + fila[b] + '</td>';
    return a;
  }, '');
  table += f + semanas.reduce( (a, _, i)=>a + '<td>' + (fila.week[i] ? fila.week[i].cantidad : 0) + '</td>', '') + '<td>' + fila.total + '</td>';   
});

It generates the following result (Note: as seen in the table in the HTML):

-----------------------------------------------------
Land     |     Product   |    25   |    26   | Total |
-----------------------------------------------------
FINCA1   |     ROSA      |   2000  |   1254  |  3254 |
-----------------------------------------------------
FINCA2   |     ROSA      |   1900  |   123   |  2023 |
-----------------------------------------------------
FINCA3   |     ROSA      |   350   |   200   |  550  |
-----------------------------------------------------
FINCA3   |     ROSA1     |   410   |    0    |  410  |
-----------------------------------------------------

Up to here everything is very good since it works excellent, what I want is to be able to totalize the columns and be as follows:

-----------------------------------------------------
Land     |     Product   |    25   |    26   | Total |
-----------------------------------------------------
FINCA1   |     ROSA      |   2000  |   1254  |  3254 |
-----------------------------------------------------
FINCA2   |     ROSA      |   1900  |   123   |  2023 |
-----------------------------------------------------
FINCA3   |     ROSA      |   350   |   200   |  550  |
-----------------------------------------------------
FINCA3   |     ROSA1     |   410   |    0    |  410  |
-----------------------------------------------------
TOTAL    |               |   4660  |   1577  |  6237 |
------------------------------------------------------ 

I have tried it in the following way:

var tableFoot = '';
var totalsem  = 0;
var totalsum  = 0;
arrayOrganizado.forEach(function(fila){
  tableFoot = semanas.reduce( (a, _, i)=>a + '<td>' + (fila.week[i] ? (totalsem += fila.week[i].cantidad) : 0) + '</td>', '') + '<td>' + (totalsum += fila.total) + '</td>';   
});

This way I do the sum and it works very well in the Total field of the table but in each of the columns of the week does not work well, Thanks for your help. Greetings!

    
asked by Fabian Sierra 16.07.2016 в 17:29
source

2 answers

0

Here is the solution, I add the changes regarding the answer of the other post:

var data = [
  {id:1, land: 'FINCA1',  product: "ROSA", variety: "R01", week:25,  quantity: 2000}, {id:1, land: 'FINCA2', product: "ROSA", variety: "R01", week:25, quantity: 1900}, {id:1, land: 'FINCA3',  product: "ROSA",    variety: "R01", week:25, quantity: 350},{id:1, land: 'FINCA3',  product: "ROSA1",   variety: "V01", week:25, quantity: 410},{id:1, land: 'FINCA1',  product: "ROSA",    variety: "A01", week:26, quantity: 1254},{id:1, land: 'FINCA2' ,  product: "ROSA",    variety: "A01", week:26, quantity: 123},{id:1, land: 'FINCA3' ,  product: "ROSA",    variety: "A01", week:26, quantity: 200}
];

//Obtengo los keys del objeto para crear el Thead de la tabla y los guardo en una variable

var tabla = document.createElement('table');
var tableHead = document.createElement('tr');

Object.keys(data[0]).forEach(prop=>{
  if(prop != 'week' && prop != 'quantity')
  tableHead.innerHTML += '<th>'+prop+'</th>';
});

var semanas = data.reduce( (semanas_, elemento)=>{
  if(semanas_.indexOf(elemento.week) == -1)
    semanas_.push(elemento.week)
  return semanas_;
}, []);

semanas.forEach( semana=>{
  tableHead.innerHTML += '<th>'+semana+'</th>';
});

/* ESTO ES NUEVO */
var total_semanas = [];
/*****************/

tableHead.innerHTML += '<th>Total</th>';
tabla.appendChild(tableHead);

var tbody = document.createElement('tbody');

tabla.appendChild(tbody);

document.querySelector('body').appendChild(tabla);

var arrayOrganizado = data.reduce((arr, item)=>{
  
  /* ESTO ES NUEVO */
  var t = total_semanas.find(e=> e.semana === item.week);
  if (t) t.total += item.quantity;
  else total_semanas.push({ semana : item.week, total : item.quantity });
  /*****************/
  
  item.week = {
    numero : item.week,
    cantidad : item.quantity
  }
  var ele = arr.find(it=>it.land === item.land && it.product === item.product);
  if(ele){
    ele.week.push(item.week);
    ele.total = ele.week.reduce((a, b)=> a + b.cantidad, 0);
  } else {
    item.week = [item.week];
    item.total = item.quantity;
    arr.push(item);
  }
  return arr;
}, []);

arrayOrganizado.forEach(fila=>{
  var f = Object.keys(fila).reduce( (a, b)=>{
    //console.log(b);
    if(b != 'week' && b != 'quantity' && b != 'total')
      return a +  '<td>' + fila[b] + '</td>';
    return a;
  }, '');
  tbody.innerHTML += f + semanas.reduce( (a, _, i)=>a + '<td>' + (fila.week[i] ? fila.week[i].cantidad : 0) + '</td>', '') + '<td>' + fila.total + '</td>';   
});


/* ESTO ES NUEVO */


var f = Object.keys(arrayOrganizado[0]).reduce( (a, b)=>{
  //console.log(b);
  if(b != 'week' && b != 'quantity' && b != 'total')
    return a +  '<td> ---- </td>';
  return a;
}, '');

tbody.innerHTML += f + total_semanas.reduce( (a, _, i)=>a + '<td>' + _.total + '</td>', '') + '<td>' + total_semanas.reduce( (a, b) => a.total + b.total) + '</td>';   
    
answered by 16.07.2016 / 20:01
source
0

I'll leave here a slightly different alternative that is not as efficient as the one you already have, but that only requires changes in one part of the code.

The idea is to calculate and draw the table as you are doing so far and, at the end of the whole, when it is already generated, add the columns from the values of the columns instead of from the array with the data.

The commented code would be something like this:

// crea una nueva fila que servirá de pie de tabla
var tableFoot = document.createElement('tr');
// atraviesa la cabecera de la tabla y para cada elemento
tabla.querySelectorAll("th").forEach(function(elem, index, arr) {
  // si el contenido es un número de semana o la palabra "Total"
  if(elem.innerHTML == parseInt(elem.innerHTML) || elem.innerHTML == "Total") {
    // inicializa la suma a 0
    var aux = 0;
    // atraviesa todas las celdas de esa columna
    tabla.querySelectorAll("td:nth-child(" + (index+1) + ")").forEach(function(e, i, a) { 
      // y añade su contenido a la suma
      aux += parseInt(e.innerHTML); 
    });
    // inserta una celda en la fila pie con el valor de la suma
    tableFoot.innerHTML += "<td>" + aux + "</td>";
  } else {
    // si no es una semana o el total, inserta una celda con guiones a la fila pie
    tableFoot.innerHTML += "<td>---</td>";
  }
});
// inserta la fila de pie a la tabla
tabla.appendChild(tableFoot);

And here I leave a demo (from the code of the answer to your previous question ):

var data = [
  {id:1, land: 'FINCA1',  product: "ROSA", variety: "R01", week:25,  quantity: 2000}, {id:1, land: 'FINCA2', product: "ROSA", variety: "R01", week:25, quantity: 1900}, {id:1, land: 'FINCA3',  product: "ROSA",    variety: "R01", week:25, quantity: 350},{id:1, land: 'FINCA3',  product: "ROSA1",   variety: "V01", week:25, quantity: 410},{id:1, land: 'FINCA1',  product: "ROSA",    variety: "A01", week:26, quantity: 1254},{id:1, land: 'FINCA2' ,  product: "ROSA",    variety: "A01", week:26, quantity: 123},{id:1, land: 'FINCA3' ,  product: "ROSA",    variety: "A01", week:26, quantity: 200}
];

//Obtengo los keys del objeto para crear el Thead de la tabla y los guardo en una variable

var tabla = document.createElement('table');
var tableHead = document.createElement('tr');

Object.keys(data[0]).forEach(prop=>{
  if(prop != 'week' && prop != 'quantity')
  tableHead.innerHTML += '<th>'+prop+'</th>';
});

var semanas = data.reduce( (semanas_, elemento)=>{
  if(semanas_.indexOf(elemento.week) == -1)
    semanas_.push(elemento.week)
  return semanas_;
}, []);

semanas.forEach( semana=>{
  tableHead.innerHTML += '<th>'+semana+'</th>';
});

tableHead.innerHTML += '<th>Total</th>';
tabla.appendChild(tableHead);

var tbody = document.createElement('tbody');

tabla.appendChild(tbody);

document.querySelector('body').appendChild(tabla);

var arrayOrganizado = data.reduce((arr, item)=>{
  item.week = {
    numero : item.week,
    cantidad : item.quantity
  }
  var ele = arr.find(it=>it.land === item.land && it.product === item.product);
  if(ele){
    ele.week.push(item.week);
    ele.total = ele.week.reduce((a, b)=> a + b.cantidad, 0);
  } else {
    item.week = [item.week];
    item.total = item.quantity;
    arr.push(item);
  }
  return arr;
}, []);

arrayOrganizado.forEach(fila=>{
  var f = Object.keys(fila).reduce( (a, b)=>{
    //console.log(b);
    if(b != 'week' && b != 'quantity' && b != 'total')
      return a +  '<td>' + fila[b] + '</td>';
    return a;
  }, '');
  tbody.innerHTML += f + semanas.reduce( (a, _, i)=>a + '<td>' + (fila.week[i] ? fila.week[i].cantidad : 0) + '</td>', '') + '<td>' + fila.total + '</td>';   
});


var tableFoot = document.createElement('tr');
tabla.querySelectorAll("th").forEach(function(elem, index, arr) {
  if(elem.innerHTML == parseInt(elem.innerHTML) || elem.innerHTML == "Total") {
    var aux = 0;
    tabla.querySelectorAll("td:nth-child(" + (index+1) + ")").forEach(function(e, i, a) { aux += parseInt(e.innerHTML); });
    tableFoot.innerHTML += "<td>" + aux + "</td>";
  } else {
    tableFoot.innerHTML += "<td>---</td>";
  }
});
tabla.appendChild(tableFoot);
    
answered by 17.07.2016 в 06:46