Export to CSV rendered columns

Hello.

When I export to CSV, the fields calculated by “renderer” do not appear.

My code:

columns: [
{ data: ‘Fecha’, type: ‘date’, dateformat: ‘DD/MM/YYYY’, readOnly: true },
{ data: ‘Campo1’, type: ‘numeric’, renderer: calcular1, className: “htRight” },
{ data: ‘Campo2’, type: ‘numeric’, renderer: calcular2, className: “htRight” },

]

The calculate function:
function calcular1(instance, td, row, col, prop, value, cellProperties) {
Handsontable.NumericCell.renderer.apply(this, arguments);
cellProperties.readOnly = true;
var colH = instance.getDataAtCell(row, 7); // colum H
var colJ = instance.getDataAtCell(row, 9); // colum J
td.innerHTML = (colH - colJ);
}

function calcular2(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.NumericCell.renderer.apply(this, arguments);
    cellProperties.readOnly = true;
    var colJ = instance.getDataAtCell(row, 9); // colum J
    var colL = instance.getDataAtCell(row, 11); // colum L
    td.innerHTML = (colJ - colL);
}

The function to export:

Exportar = function () {

    exportPlugin = hot.getPlugin('exportFile');

    exportPlugin.downloadFile('csv', {
        filename: 'Example',
        columnHeaders: true,         
        columnDelimiter: ';'
    });
}

The fields values of “Campo1” and “Campo2” do not appear.

Thanks.

Hi @orijuan

It would be the best if you could create a demo where we will be able to replicate the same situation. Can you share it please?

Hello.

I can not send you a demo. Error appears …

I send them the code of the file js.

APP.JS

angular.module(‘app’, [])

.controller(‘AppCtrl’, function ($scope) {

$scope.data = [{"Fecha":"01/03/2017","Nombre_Campanya":null,"Fecha_Inicio_Lote":null,"Fin_Cierre_Lote":null,"Num_Registros_Entregados":100,"Entregado_No_Tocado":null,"Entregado_En_Curso":null,"Entregado_Cerrado":50,"Cerrado_No_Util":null,"Cerrado_Util":20,"Util_No_Venta":null,"Util_Solicitud_Venta":10,"Horas_productivas":20,"Cliente_Nuevo_Gas":null,"Servigas":null,"Retencion_Servigas":null,"Servielectric":null,"Agua_Caliente":false,"Secado_Ropa":false,"Coccion":false,"Calefaccion":false,"Ratio_Registros_Entregados":null,"Ratio_Registros_Cerrados":null,"Ratio_Solicitudes_Hora":null,"Ratio_Cerrados":null,"Ratio_Contactos":null,"Motivo1":null,"Motivo2":null,"Motivo3":null,"Motivo4":null,"Motivo5":null,"Otros":null},{"Fecha":"02/03/2017","Nombre_Campanya":null,"Fecha_Inicio_Lote":null,"Fin_Cierre_Lote":null,"Num_Registros_Entregados":null,"Entregado_No_Tocado":null,"Entregado_En_Curso":null,"Entregado_Cerrado":null,"Cerrado_No_Util":null,"Cerrado_Util":null,"Util_No_Venta":null,"Util_Solicitud_Venta":null,"Horas_productivas":null,"Cliente_Nuevo_Gas":null,"Servigas":null,"Retencion_Servigas":null,"Servielectric":null,"Agua_Caliente":false,"Secado_Ropa":false,"Coccion":false,"Calefaccion":false,"Ratio_Registros_Entregados":null,"Ratio_Registros_Cerrados":null,"Ratio_Solicitudes_Hora":null,"Ratio_Cerrados":null,"Ratio_Contactos":null,"Motivo1":null,"Motivo2":null,"Motivo3":null,"Motivo4":null,"Motivo5":null,"Otros":null},{"Fecha":"03/03/2017","Nombre_Campanya":null,"Fecha_Inicio_Lote":null,"Fin_Cierre_Lote":null,"Num_Registros_Entregados":null,"Entregado_No_Tocado":null,"Entregado_En_Curso":null,"Entregado_Cerrado":null,"Cerrado_No_Util":null,"Cerrado_Util":null,"Util_No_Venta":null,"Util_Solicitud_Venta":null,"Horas_productivas":null,"Cliente_Nuevo_Gas":null,"Servigas":null,"Retencion_Servigas":null,"Servielectric":null,"Agua_Caliente":false,"Secado_Ropa":false,"Coccion":false,"Calefaccion":false,"Ratio_Registros_Entregados":null,"Ratio_Registros_Cerrados":null,"Ratio_Solicitudes_Hora":null,"Ratio_Cerrados":null,"Ratio_Contactos":null,"Motivo1":null,"Motivo2":null,"Motivo3":null,"Motivo4":null,"Motivo5":null,"Otros":null}];

var hot = [];
var exportPlugin = [];

loadDatos = function () {
          
        var hotElement = document.getElementById('gridDatos');

        var hotSettings = {
            data: $scope.data,
            //stretchH: 'none',
            //autoWrapRow: false,
            height: 550,
            colWidths: [110, 200, 50, 50, 10, 47, 47],
            rowHeaders: false,
            columnSorting: true,
            sortIndicator: true,
            fillHandle: true,
            columns: [
                { data: 'Fecha', type: 'date', dateformat: 'DD/MM/YYYY', readOnly: true  },
                { data: 'Nombre_Campanya', type: 'text' },
                { data: 'Fecha_Inicio_Lote', type: 'date', dateformat: 'DD/MM/YYYY' },
                { data: 'Fin_Cierre_Lote', type: 'date', dateformat: 'DD/MM/YYYY' },
                { data: 'Num_Registros_Entregados', type: 'numeric' },
                { data: 'Entregado_No_Tocado', type: 'numeric' },
                { data: 'Entregado_En_Curso', type: 'numeric' },
                { data: 'Entregado_Cerrado', type: 'numeric' },
                { data: 'Cerrado_No_Util', type: 'numeric', renderer: calcular1, className: "htRight" },
                { data: 'Cerrado_Util', type: 'numeric' },
                { data: 'Util_No_Venta', type: 'numeric', renderer: calcular2, className: "htRight" },
                { data: 'Util_Solicitud_Venta', type: 'numeric' },
                { data: 'Horas_productivas', type: 'numeric' },
                { data: 'Cliente_Nuevo_Gas', type: 'text' },
                { data: 'Servigas', type: 'text' },
                { data: 'Retencion_Servigas', type: 'text' },
                { data: 'Servielectric', type: 'text' },
                { data: 'Agua_Caliente', type: 'checkbox', className: "htCenter htMiddle" },
                { data: 'Secado_Ropa', type: 'checkbox', className: "htCenter htMiddle" },
                { data: 'Coccion', type: 'checkbox', className: "htCenter htMiddle" },
                { data: 'Calefaccion', type: 'checkbox', className: "htCenter htMiddle" },
                { data: 'Ratio_Registros_Entregados', type: 'numeric', renderer: calcularRatio1, className: "htRight" },
                { data: 'Ratio_Registros_Cerrados', type: 'numeric', renderer: calcularRatio2, className: "htRight" },
                { data: 'Ratio_Solicitudes_Hora', type: 'numeric', renderer: calcularRatio3, className: "htRight" },
                { data: 'Ratio_Cerrados', type: 'numeric', renderer: calcularRatio4, className: "htRight" },
                { data: 'Ratio_Contactos', type: 'numeric', renderer: calcularRatio5, className: "htRight" },
                { data: 'Motivo1', type: 'text' },
                { data: 'Motivo2', type: 'text' },
                { data: 'Motivo3', type: 'text' },
                { data: 'Motivo4', type: 'text' },
                { data: 'Motivo5', type: 'text' },
                { data: 'Otros', type: 'text' }
            ],
            colHeaders: [
                'Fecha',
                'Nombre Campaña',
                'Fecha Inicio Lote',
                'Fin Cierre Lote',
                '# registros ENTREGADOS',
                'Entregado NO TOCADO',
                'Entregado EN CURSO',
                'Entregado CERRADO',
                'Cerrado NO ÚTIL',
                'Cerrado ÚTIL',
                'Útil NO VENTA',
                'Útil SOLICITUD VENTA',
                'HORAS productivas',
                'Cliente Nuevo Gas',
                'Servigas',
                'Retención Servigas',
                'Servielectric',
                'Agua Caliente',
                'Secado Ropa',
                'Cocción',
                'Calefacción',
                'Solicitudes s/registros entregados',
                'Solicitudes s/registros cerrados',
                'Solicitudes por hora',
                '% Cerrados s/entregados',
                '% Contactos útiles',
                'Motivo 1',
                'Motivo 2',
                'Motivo 3',
                'Motivo 4',
                'Motivo 5',
                'Otros'
            ],
            nestedHeaders: [
                [
                    { label: '', colspan: 13 },
                    { label: 'Detalle Solicitud de venta', colspan: 8 },
                    { label: 'RATIOS', colspan: 5 },
                    { label: '', colspan: 6 }
                ],
                [
                { label: '', colspan: 13 },
                'Energía',
                { label: 'Servicios', colspan: 3 },
                { label: 'Aparatos', colspan: 4 },
                '1', '2', '3', '4', '5',
                { label: 'Motivos útil NO-Venta', colspan: 6 }
                ], [
                'Fecha',
                'Nombre Campaña',
                'Fecha Inicio Lote',
                'Fin Cierre Lote',
                { label: '<label># registros<br/>ENTREGADOS (1)</label>', colspan: 1 },
                { label: '<label>Entregado<br/>NO TOCADO</label>', colspan: 1 },
                { label: '<label>Entregado<br/>EN CURSO</label>', colspan: 1 },
                { label: '<label>Entregado<br/>CERRADO (2)</label>', colspan: 1 },
                { label: '<label>Cerrado<br/>NO ÚTIL</label>', colspan: 1 },
                { label: '<label>Cerrado<br/>ÚTIL (3)</label>', colspan: 1 },
                { label: '<label>Útil<br/>NO VENTA</label>', colspan: 1 },
                { label: '<label>Útil<br/>SOLICITUD<br/>VENTA (4)</label>', colspan: 1 },
                { label: '<label>HORAS<br/>productivas (5)</label>', colspan: 1 },
                { label: '<label>Cliente<br/>Nuevo Gas</label>', colspan: 1 },
                'Servigas',
                { label: '<label>Retención<br/>Servigas</label>', colspan: 1 },
                'Servielectric',
                { label: '<label>Agua<br/>Caliente</label>', colspan: 1 },
                { label: '<label>Secado<br/>Ropa</label>', colspan: 1 },
                'Cocción',
                'Calefacción',
                { label: '<label>Solicitudes<br/>s/registros<br/>entregados<br/>[=(4)/(1)]</label>', colspan: 1 },
                { label: '<label>Solicitudes<br/>s/registros<br/>cerrados<br/>[=(4)/(2)]</label>', colspan: 1 },
                { label: '<label>Solicitudes<br/>por hora<br/>[=(4)/(5)]</label>', colspan: 1 },
                { label: '<label>% Cerrados<br/>s/entregados<br/>[=(2)/(1)]</label>', colspan: 1 },
                { label: '<label>% Contactos<br/>útiles<br/>[=(3)/(1)]</label>', colspan: 1 },
                'Motivo 1',
                'Motivo 2',
                'Motivo 3',
                'Motivo 4',
                'Motivo 5',
                'Otros']
            ],
            search: true,
            //filters: true,
            //dropdownMenu: true,
            afterChange: function (change, source) {
                    if (source === 'loadData') {
                        return; //don't save this change
                    }

                    var datoGrabar = JSON.stringify({ data: change });
                    //console.log('grabar cambio: ', datoGrabar);

            },
            afterGetColHeader: function (col, TH) {
                var TR = TH.parentNode;
                var THEAD = TR.parentNode;
                var headerLevel = (-1) * THEAD.childNodes.length + Array.prototype.indexOf.call(THEAD.childNodes, TR);

                function applyClass(elem, className) {
                    if (!Handsontable.Dom.hasClass(elem, className)) {
                        Handsontable.Dom.addClass(elem, className);
                    }
                }

                if (headerLevel === -3) {

                    if (col === 13) {
                        applyClass(TH, 'color1');
                    } else if (col === 21) {
                        applyClass(TH, 'color2');
                    } else if (col == 0 || col == 26) {
                        applyClass(TH, 'color3');
                    }

                    // third level from the top
                } else if (headerLevel === -2) {

                    if (col == 2 || col == 13 || col == 14 ||col == 17 || col == 26) {
                        applyClass(TH, 'color1');
                    } else if (col == 21 || col == 22 || col == 23 || col == 24 || col == 25) {
                        applyClass(TH, 'color2');
                    } else if (col == 0 || col == 5) {
                        applyClass(TH, 'color3');
                    }

                    // fourth level from the top
                } else if (headerLevel === -1) {
                    if (col == 0 || col == 4 || col == 7 || col == 9 || col == 11 || col == 12 || col == 21 || col == 22 || col == 23 || col == 24 || col == 25) {
                        applyClass(TH, 'color1');
                    } else if (col == 1 || col == 2 || col == 3 || col == 5 || col == 6 || col == 8 || col == 10 || col == 13 || col == 14 || col == 15 || col == 16 || col == 17 || col == 18 || col == 19 || col == 20 || col == 26 || col == 27 || col == 28 || col == 29 || col == 30 || col == 31) {
                        applyClass(TH, 'color2');
                    }
                }



            }
                

        }

        hot = new Handsontable(hotElement, hotSettings);

}


//Carga los datos al entrar
loadDatos();



// Exportación a CSV
$scope.Exportar = function () {

    exportPlugin = hot.getPlugin('exportFile');

    exportPlugin.downloadFile('csv', {
        filename: 'Example',
        columnHeaders: true,        // default false, exports the column headers
        columnDelimiter: ';'
    });
}



// Calcula 1
function calcular1(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.NumericCell.renderer.apply(this, arguments);
    cellProperties.readOnly = true;
    var colH = instance.getDataAtCell(row, 7); // columna H
    var colJ = instance.getDataAtCell(row, 9); // columna J
    td.innerHTML = (colH - colJ);
}

// Calcula 2
function calcular2(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.NumericCell.renderer.apply(this, arguments);
    cellProperties.readOnly = true;
    var colJ = instance.getDataAtCell(row, 9); // columna J
    var colL = instance.getDataAtCell(row, 11); // columna L
    td.innerHTML = (colJ - colL);
}


// Calcula el Ratio 1
function calcularRatio1(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.NumericCell.renderer.apply(this, arguments);
    cellProperties.readOnly = true;

    var colL = instance.getDataAtCell(row, 11); // columna L
    var colE = instance.getDataAtCell(row, 4); // columna E

    if (colE > 0) {
        td.innerHTML = parseFloat((colL / colE) * 100).toFixed(2) + '%'; // con dos decimales
    } else {
        td.innerHTML = '-';
    }
}


// Calcula el Ratio 2
function calcularRatio2(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.NumericCell.renderer.apply(this, arguments);
    cellProperties.readOnly = true;

    var colL = instance.getDataAtCell(row, 11); // columna L
    var colH = instance.getDataAtCell(row, 7); // columna H

    if (colH > 0) {
        td.innerHTML = parseFloat((colL / colH) * 100).toFixed(2) + '%'; // con dos decimales
    } else {
        td.innerHTML = '-';
    }
}

// Calcula el Ratio 3
function calcularRatio3(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.NumericCell.renderer.apply(this, arguments);
    cellProperties.readOnly = true;

    var colL = instance.getDataAtCell(row, 11); // columna L
    var colM = instance.getDataAtCell(row, 12); // columna M

    if (colM > 0) {
        td.innerHTML = parseFloat((colL / colM)).toFixed(2); // con dos decimales
    } else {
        td.innerHTML = '-';
    }
}

// Calcula el Ratio 4
function calcularRatio4(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.NumericCell.renderer.apply(this, arguments);
    cellProperties.readOnly = true;

    var colH = instance.getDataAtCell(row, 7); // columna H
    var colE = instance.getDataAtCell(row, 4); // columna E

    if (colE > 0) {
        td.innerHTML = parseFloat((colH / colE) * 100).toFixed(2) + '%'; // con dos decimales
    } else {
        td.innerHTML = '-';
    }
}

// Calcula el Ratio 5
function calcularRatio5(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.NumericCell.renderer.apply(this, arguments);
    cellProperties.readOnly = true;

    var colJ = instance.getDataAtCell(row, 9); // columna J
    var colH = instance.getDataAtCell(row, 7); // columna H

    if (colH > 0) {
        td.innerHTML = parseFloat((colJ / colH) * 100).toFixed(2) + '%'; // con dos decimales
    } else {
        td.innerHTML = '-';
    }
}

});

INDEX.HTML

<div layout="row" flex>

	<div id="gridDatos" class="dataHandsonTable" ></div>

	  
		 <md-button ng-click="Exportar()" ng-hide="cargando">Export to CSV</md-button>
	  

</div>

Thank you.

What error do you get @orijuan when you create a demo?

Hello.

I try uploading a zip file with the js and html files, but it will not let me upload it.

If you can try what I sent before, you will see that the data of the calculated columns does not appear in the CSV file.

Thanks for your quick response.

Thank you very much. I think I know what is the problem. You are rendering the values but do not save them.
Please try to use setDataAtCell() to save this values inside the renderer. Then they should be visible in the .csv file.

Thank you very much.
Sorry for my ignorance, but I do not know where to put setDataAtCell in my code.

I tried:

function calcular1(instance, td, row, col, prop, value, cellProperties) {
Handsontable.NumericCell.renderer.apply(this, arguments);
cellProperties.readOnly = true;
var colH = instance.getDataAtCell(row, 7); // columna H
var colJ = instance.getDataAtCell(row, 9); // columna J
td.innerHTML = (colH - colJ);

    **hot.setDataAtCell(row, col, td.innerHTML);**

}

and also:

function calcular1(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.NumericCell.renderer.apply(this, arguments);
    cellProperties.readOnly = true;
    var colH = instance.getDataAtCell(row, 7); // columna H
    var colJ = instance.getDataAtCell(row, 9); // columna J
    td.innerHTML = (colH - colJ);

    **hot('setDataAtCell', row, col, td.innerHTML);**

}

But it does not work. It gives me an error (setDataAtCell is not a function …).

Where and how do I have to setDataAtCell?

Thank you.

Hi @orijuan

I would need to get a working demo to test it but hot should be replaced with the instance name. Maybe you will also need to add instance_name.rendeR() method but inside an already made renderer you shouldn’t.

Please create a demo with the renderer and I’ll check it.

Hello.

I tried with instance.setDataAtCell(…) and working when export to CSV, but the grid is very slow.

I send you my code:

angular.module(‘app’, [])

.controller(‘AppCtrl’, function ($scope) {

$scope.data = [{"Fecha":"01/03/2017","Nombre_Campanya":null,"Fecha_Inicio_Lote":null,"Fin_Cierre_Lote":null,"Num_Registros_Entregados":100,"Entregado_No_Tocado":null,"Entregado_En_Curso":null,"Entregado_Cerrado":50,"Cerrado_No_Util":null,"Cerrado_Util":20,"Util_No_Venta":null,"Util_Solicitud_Venta":10,"Horas_productivas":20,"Cliente_Nuevo_Gas":null,"Servigas":null,"Retencion_Servigas":null,"Servielectric":null,"Agua_Caliente":false,"Secado_Ropa":false,"Coccion":false,"Calefaccion":false,"Ratio_Registros_Entregados":null,"Ratio_Registros_Cerrados":null,"Ratio_Solicitudes_Hora":null,"Ratio_Cerrados":null,"Ratio_Contactos":null,"Motivo1":null,"Motivo2":null,"Motivo3":null,"Motivo4":null,"Motivo5":null,"Otros":null},{"Fecha":"02/03/2017","Nombre_Campanya":null,"Fecha_Inicio_Lote":null,"Fin_Cierre_Lote":null,"Num_Registros_Entregados":null,"Entregado_No_Tocado":null,"Entregado_En_Curso":null,"Entregado_Cerrado":null,"Cerrado_No_Util":null,"Cerrado_Util":null,"Util_No_Venta":null,"Util_Solicitud_Venta":null,"Horas_productivas":null,"Cliente_Nuevo_Gas":null,"Servigas":null,"Retencion_Servigas":null,"Servielectric":null,"Agua_Caliente":false,"Secado_Ropa":false,"Coccion":false,"Calefaccion":false,"Ratio_Registros_Entregados":null,"Ratio_Registros_Cerrados":null,"Ratio_Solicitudes_Hora":null,"Ratio_Cerrados":null,"Ratio_Contactos":null,"Motivo1":null,"Motivo2":null,"Motivo3":null,"Motivo4":null,"Motivo5":null,"Otros":null},{"Fecha":"03/03/2017","Nombre_Campanya":null,"Fecha_Inicio_Lote":null,"Fin_Cierre_Lote":null,"Num_Registros_Entregados":null,"Entregado_No_Tocado":null,"Entregado_En_Curso":null,"Entregado_Cerrado":null,"Cerrado_No_Util":null,"Cerrado_Util":null,"Util_No_Venta":null,"Util_Solicitud_Venta":null,"Horas_productivas":null,"Cliente_Nuevo_Gas":null,"Servigas":null,"Retencion_Servigas":null,"Servielectric":null,"Agua_Caliente":false,"Secado_Ropa":false,"Coccion":false,"Calefaccion":false,"Ratio_Registros_Entregados":null,"Ratio_Registros_Cerrados":null,"Ratio_Solicitudes_Hora":null,"Ratio_Cerrados":null,"Ratio_Contactos":null,"Motivo1":null,"Motivo2":null,"Motivo3":null,"Motivo4":null,"Motivo5":null,"Otros":null}];

var hot = [];
var exportPlugin = [];

loadDatos = function () {
          
        var hotElement = document.getElementById('gridDatos');

        var hotSettings = {
            data: $scope.data,
            //stretchH: 'none',
            //autoWrapRow: false,
            height: 550,
            colWidths: [110, 200, 50, 50, 10, 47, 47],
            rowHeaders: false,
            columnSorting: true,
            sortIndicator: true,
            fillHandle: true,
            columns: [
                { data: 'Fecha', type: 'date', dateformat: 'DD/MM/YYYY', readOnly: true  },
                { data: 'Nombre_Campanya', type: 'text' },
                { data: 'Fecha_Inicio_Lote', type: 'date', dateformat: 'DD/MM/YYYY' },
                { data: 'Fin_Cierre_Lote', type: 'date', dateformat: 'DD/MM/YYYY' },
                { data: 'Num_Registros_Entregados', type: 'numeric' },
                { data: 'Entregado_No_Tocado', type: 'numeric' },
                { data: 'Entregado_En_Curso', type: 'numeric' },
                { data: 'Entregado_Cerrado', type: 'numeric' },
                { data: 'Cerrado_No_Util', type: 'numeric', renderer: calcular1, className: "htRight" },
                { data: 'Cerrado_Util', type: 'numeric' },
                { data: 'Util_No_Venta', type: 'numeric', renderer: calcular2, className: "htRight" },
                { data: 'Util_Solicitud_Venta', type: 'numeric' },
                { data: 'Horas_productivas', type: 'numeric' },
                { data: 'Cliente_Nuevo_Gas', type: 'text' },
                { data: 'Servigas', type: 'text' },
                { data: 'Retencion_Servigas', type: 'text' },
                { data: 'Servielectric', type: 'text' },
                { data: 'Agua_Caliente', type: 'checkbox', className: "htCenter htMiddle" },
                { data: 'Secado_Ropa', type: 'checkbox', className: "htCenter htMiddle" },
                { data: 'Coccion', type: 'checkbox', className: "htCenter htMiddle" },
                { data: 'Calefaccion', type: 'checkbox', className: "htCenter htMiddle" },
                { data: 'Ratio_Registros_Entregados', type: 'numeric', renderer: calcularRatio1, className: "htRight" },
                { data: 'Ratio_Registros_Cerrados', type: 'numeric', renderer: calcularRatio2, className: "htRight" },
                { data: 'Ratio_Solicitudes_Hora', type: 'numeric', renderer: calcularRatio3, className: "htRight" },
                { data: 'Ratio_Cerrados', type: 'numeric', renderer: calcularRatio4, className: "htRight" },
                { data: 'Ratio_Contactos', type: 'numeric', renderer: calcularRatio5, className: "htRight" },
                { data: 'Motivo1', type: 'text' },
                { data: 'Motivo2', type: 'text' },
                { data: 'Motivo3', type: 'text' },
                { data: 'Motivo4', type: 'text' },
                { data: 'Motivo5', type: 'text' },
                { data: 'Otros', type: 'text' }
            ],
            colHeaders: [
                'Fecha',
                'Nombre Campaña',
                'Fecha Inicio Lote',
                'Fin Cierre Lote',
                '# registros ENTREGADOS',
                'Entregado NO TOCADO',
                'Entregado EN CURSO',
                'Entregado CERRADO',
                'Cerrado NO ÚTIL',
                'Cerrado ÚTIL',
                'Útil NO VENTA',
                'Útil SOLICITUD VENTA',
                'HORAS productivas',
                'Cliente Nuevo Gas',
                'Servigas',
                'Retención Servigas',
                'Servielectric',
                'Agua Caliente',
                'Secado Ropa',
                'Cocción',
                'Calefacción',
                'Solicitudes s/registros entregados',
                'Solicitudes s/registros cerrados',
                'Solicitudes por hora',
                '% Cerrados s/entregados',
                '% Contactos útiles',
                'Motivo 1',
                'Motivo 2',
                'Motivo 3',
                'Motivo 4',
                'Motivo 5',
                'Otros'
            ],
            nestedHeaders: [
                [
                    { label: '', colspan: 13 },
                    { label: 'Detalle Solicitud de venta', colspan: 8 },
                    { label: 'RATIOS', colspan: 5 },
                    { label: '', colspan: 6 }
                ],
                [
                { label: '', colspan: 13 },
                'Energía',
                { label: 'Servicios', colspan: 3 },
                { label: 'Aparatos', colspan: 4 },
                '1', '2', '3', '4', '5',
                { label: 'Motivos útil NO-Venta', colspan: 6 }
                ], [
                'Fecha',
                'Nombre Campaña',
                'Fecha Inicio Lote',
                'Fin Cierre Lote',
                { label: '<label># registros<br/>ENTREGADOS (1)</label>', colspan: 1 },
                { label: '<label>Entregado<br/>NO TOCADO</label>', colspan: 1 },
                { label: '<label>Entregado<br/>EN CURSO</label>', colspan: 1 },
                { label: '<label>Entregado<br/>CERRADO (2)</label>', colspan: 1 },
                { label: '<label>Cerrado<br/>NO ÚTIL</label>', colspan: 1 },
                { label: '<label>Cerrado<br/>ÚTIL (3)</label>', colspan: 1 },
                { label: '<label>Útil<br/>NO VENTA</label>', colspan: 1 },
                { label: '<label>Útil<br/>SOLICITUD<br/>VENTA (4)</label>', colspan: 1 },
                { label: '<label>HORAS<br/>productivas (5)</label>', colspan: 1 },
                { label: '<label>Cliente<br/>Nuevo Gas</label>', colspan: 1 },
                'Servigas',
                { label: '<label>Retención<br/>Servigas</label>', colspan: 1 },
                'Servielectric',
                { label: '<label>Agua<br/>Caliente</label>', colspan: 1 },
                { label: '<label>Secado<br/>Ropa</label>', colspan: 1 },
                'Cocción',
                'Calefacción',
                { label: '<label>Solicitudes<br/>s/registros<br/>entregados<br/>[=(4)/(1)]</label>', colspan: 1 },
                { label: '<label>Solicitudes<br/>s/registros<br/>cerrados<br/>[=(4)/(2)]</label>', colspan: 1 },
                { label: '<label>Solicitudes<br/>por hora<br/>[=(4)/(5)]</label>', colspan: 1 },
                { label: '<label>% Cerrados<br/>s/entregados<br/>[=(2)/(1)]</label>', colspan: 1 },
                { label: '<label>% Contactos<br/>útiles<br/>[=(3)/(1)]</label>', colspan: 1 },
                'Motivo 1',
                'Motivo 2',
                'Motivo 3',
                'Motivo 4',
                'Motivo 5',
                'Otros']
            ],
            search: true,
            //filters: true,
            //dropdownMenu: true,
            afterChange: function (change, source) {
                    if (source === 'loadData') {
                        return; //don't save this change
                    }

                    var datoGrabar = JSON.stringify({ data: change });
                    //console.log('grabar cambio: ', datoGrabar);

            },
            afterGetColHeader: function (col, TH) {
                var TR = TH.parentNode;
                var THEAD = TR.parentNode;
                var headerLevel = (-1) * THEAD.childNodes.length + Array.prototype.indexOf.call(THEAD.childNodes, TR);

                function applyClass(elem, className) {
                    if (!Handsontable.Dom.hasClass(elem, className)) {
                        Handsontable.Dom.addClass(elem, className);
                    }
                }

                if (headerLevel === -3) {

                    if (col === 13) {
                        applyClass(TH, 'color1');
                    } else if (col === 21) {
                        applyClass(TH, 'color2');
                    } else if (col == 0 || col == 26) {
                        applyClass(TH, 'color3');
                    }

                    // third level from the top
                } else if (headerLevel === -2) {

                    if (col == 2 || col == 13 || col == 14 ||col == 17 || col == 26) {
                        applyClass(TH, 'color1');
                    } else if (col == 21 || col == 22 || col == 23 || col == 24 || col == 25) {
                        applyClass(TH, 'color2');
                    } else if (col == 0 || col == 5) {
                        applyClass(TH, 'color3');
                    }

                    // fourth level from the top
                } else if (headerLevel === -1) {
                    if (col == 0 || col == 4 || col == 7 || col == 9 || col == 11 || col == 12 || col == 21 || col == 22 || col == 23 || col == 24 || col == 25) {
                        applyClass(TH, 'color1');
                    } else if (col == 1 || col == 2 || col == 3 || col == 5 || col == 6 || col == 8 || col == 10 || col == 13 || col == 14 || col == 15 || col == 16 || col == 17 || col == 18 || col == 19 || col == 20 || col == 26 || col == 27 || col == 28 || col == 29 || col == 30 || col == 31) {
                        applyClass(TH, 'color2');
                    }
                }



            }
                

        }

        hot = new Handsontable(hotElement, hotSettings);
		 
}


//Carga los datos al entrar
loadDatos();



// Exportación a CSV
$scope.Exportar = function () {
    exportPlugin = hot.getPlugin('exportFile');
    exportPlugin.downloadFile('csv', {
        filename: 'Example',
        columnHeaders: true,        // default false, exports the column headers
        columnDelimiter: ';'
    });
}



// Calcula 1
function calcular1(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.NumericCell.renderer.apply(this, arguments);
    cellProperties.readOnly = true;
    var colH = instance.getDataAtCell(row, 7); // columna H
    var colJ = instance.getDataAtCell(row, 9); // columna J
    td.innerHTML = (colH - colJ);
	//instance.setDataAtCell(row, col, td.innerHTML);
}

// Calcula 2
function calcular2(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.NumericCell.renderer.apply(this, arguments);
    cellProperties.readOnly = true;
    var colJ = instance.getDataAtCell(row, 9); // columna J
    var colL = instance.getDataAtCell(row, 11); // columna L
    td.innerHTML = (colJ - colL);
	//instance.setDataAtCell(row, col, td.innerHTML);
}


// Calcula el Ratio 1
function calcularRatio1(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.NumericCell.renderer.apply(this, arguments);
    cellProperties.readOnly = true;

    var colL = instance.getDataAtCell(row, 11); // columna L
    var colE = instance.getDataAtCell(row, 4); // columna E

    if (colE > 0) {
        td.innerHTML = parseFloat((colL / colE) * 100).toFixed(2) + '%'; // con dos decimales
    } else {
        td.innerHTML = '-';
    }
	//instance.setDataAtCell(row, col, td.innerHTML);
}


// Calcula el Ratio 2
function calcularRatio2(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.NumericCell.renderer.apply(this, arguments);
    cellProperties.readOnly = true;

    var colL = instance.getDataAtCell(row, 11); // columna L
    var colH = instance.getDataAtCell(row, 7); // columna H

    if (colH > 0) {
        td.innerHTML = parseFloat((colL / colH) * 100).toFixed(2) + '%'; // con dos decimales
    } else {
        td.innerHTML = '-';
    }
	//instance.setDataAtCell(row, col, td.innerHTML);
}

// Calcula el Ratio 3
function calcularRatio3(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.NumericCell.renderer.apply(this, arguments);
    cellProperties.readOnly = true;

    var colL = instance.getDataAtCell(row, 11); // columna L
    var colM = instance.getDataAtCell(row, 12); // columna M

    if (colM > 0) {
        td.innerHTML = parseFloat((colL / colM)).toFixed(2); // con dos decimales
    } else {
        td.innerHTML = '-';
    }
	//instance.setDataAtCell(row, col, td.innerHTML);
}

// Calcula el Ratio 4
function calcularRatio4(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.NumericCell.renderer.apply(this, arguments);
    cellProperties.readOnly = true;

    var colH = instance.getDataAtCell(row, 7); // columna H
    var colE = instance.getDataAtCell(row, 4); // columna E

    if (colE > 0) {
        td.innerHTML = parseFloat((colH / colE) * 100).toFixed(2) + '%'; // con dos decimales
    } else {
        td.innerHTML = '-';
    }
	//instance.setDataAtCell(row, col, td.innerHTML);
}

// Calcula el Ratio 5
function calcularRatio5(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.NumericCell.renderer.apply(this, arguments);
    cellProperties.readOnly = true;

    var colJ = instance.getDataAtCell(row, 9); // columna J
    var colH = instance.getDataAtCell(row, 7); // columna H

    if (colH > 0) {
        td.innerHTML = parseFloat((colJ / colH) * 100).toFixed(2) + '%'; // con dos decimales
    } else {
        td.innerHTML = '-';
    }
	//instance.setDataAtCell(row, col, td.innerHTML);
}

});

Could it be that the problem is to use renderer in the columns?

Thank you.

Hi @orijuan

setDataAtCell can be pretty slow if the table has many rows and columns. We are working on an option for an eco-rendering. This will allow us to refresh only data that is changed and in the result - will boost performance.

Thank you.

I hope you have it soon. How can I know when it’s done?

Greetings.

@orijuan

according to our Roadmap for 2017 it is planned for this quarter. I think that maybe the end of May is a positive day to consider as a starting point.

Perfect!

Thank you very much.

you’re welcome @orijuan
have a great day!