general_grid.js

/**
* Este script agrupa y simplifica muchas funciones de la grid del DHTMLX.
* {@link https://docs.dhtmlx.com/grid__index.html} 
* @module generalGrid
*/

/**
*Toma el valor o el html de una celda (Esto depende si el valor existe o no)
*@param {Object} grid dhtmlXGridFromTable grid a la cual pertenecen las columnas  
*@param {String} row indice de la fila a la cual se le desea tomar su valor
*@param {String} col indice de la columna 
*@returns {String} valor de la celda
*/
function getGCValue(grid, row, col) {
    var str = grid.cells2(row, col).getValue();
    if (str == undefined) {
        str = grid.cells(row, col).cell.innerHTML;
    }
    return str;
}

/**
*Toma el texto de una celda de la grid
*@param {Object} grid objeto dhtmlXGridFromTable grid a la cual pertenecen las columnas  
*@param {String} row indice de la fila a la cual se le desea tomar su valor
*@param {String} col indice de la columna 
*@returns {String} texto de la celda
*/
function getGCText(grid, row, col) {
    var cell = grid.cells2(row, col).cell;
    if (typeof (cell.textContent) != 'undefined') {
        str = cell.textContent;
    }
    else {
        str = cell.innerText;
    }
    return str;
}

/**
*Elimina todas las filas de la grid  
*@param {Object} grid objeto dhtmlXGridFromTable grid  
*/
function gridClearAll(grid) {
    grid.clearAll();
}

/**
*Convierte una grid en un arreglo bidimensional
*@param {Object} grid objeto dhtmlXGridFromTable grid  
*@param {Boolean} onlyText true serializar la grid en formato CSV, solo los valores de texto se va a serializar
*@returns {Array} Datos en arreglo
*/
function getGridArray(grid, onlyText) {
    grid.setCSVDelimiter('¬')
    var data = grid.serializeToCSV(onlyText);
    var arrRows = data.split('\n');

    var arrData = new Array(arrRows.length);

    for (var iRow = 0; iRow < arrRows.length; iRow++) {
        arrData[iRow] = arrRows[iRow].split('¬');
    }

    return arrData;
}

/**
*Obtiene la configuración de un file desde el objeto global mediante el id.
*@param {object} grid Objeto de la grid
*@param {string} colsToXml no se usa
*@returns {string} xml con datos de retorno
*/
function getGridXML2(grid, colsToXml) {
    var xml = '';
    grid.forEachRow(
        function (rid) {
            xml += '<r id="{0}">'.format(rid);
            grid.forEachCell(rid, function (cell, cind) {
                xml += '<c>{0}</c>'.format(cell.getValue());
            })
            xml += '</r>';
        });
    return xml;
}

/**
*Devuelve el XML de una grid
*@param {Array} arrGrid arreglo bidemensional con los datos de la grid
*@param {String} cbCols conjunto de  indice de los checkbox separados por comas  
*@param {String} xmlCols columnas que se van a generar en el xml, separado por comas
*@returns {String} datos en XML 
*/
function getGridXML(arrGrid, cbCols, xmlCols) {
    var xmlGrid = '';
    var value = '';
    cbCols = ',' + cbCols + ',';

    if (xmlCols != undefined) {
        xmlCols = ',' + xmlCols + ',';
    }

    for (var iRow = 0; iRow < arrGrid.length; iRow++) {
        xmlGrid += '<r id="' + iRow + '">';
        for (var iCol = 0; iCol < arrGrid[0].length; iCol++) {
            if (xmlCols == undefined || xmlCols.indexOf(',' + iCol + ',') >= 0) {
                value = arrGrid[iRow][iCol];
                if (cbCols.indexOf(',' + iCol + ',') >= 0) {
                    value = (value == '1') ? '1' : '0';
                }
                xmlGrid += '<c>' + value + '</c>';
            }
        }
        xmlGrid += '</r>';
    }

    return xmlGrid;
}

/**
*Limpia los datos de una columna de la grid
*@param {Object} grid objeto dhtmlXGridFromTable grid  
*@param {String} colIndex Indice de la columna a limpiar
*/
function clearGridColumn(grid, colIndex) {
    for (var i = 0; i < grid.getRowsNum(); i++) {
        grid.cells2(i, colIndex).setValue('');
    }
}

/**
*Establece el ancho de las columnas pertenecientes a la grid 
*@param {Object} grid objeto dhtmlXGridFromTable grid  
*@param {String} colW Ancho deseado de las columnas   
*/
function setGridColWidth(grid, colWidth) {
    var arrColWidth = colWidth.split(',');
    for (var i = 0; i < arrColWidth.length; i++) {
        grid.setColWidth(i, parseInt(arrColWidth[i]));
    }
}

function selectRow(cell) {
    var grid = cell.parentNode.grid;
    var rId = cell.parentNode.idd;
    grid.selectRowById(rId, false, true, false);
}

/**
*Configuran el objeto y los valores iniciales de la grid
*@param {Object} grid objeto dhtmlXGridFromTable grid  
*@param {Object} config objeto con la configuracion de la grid 
*/
function setGridConfig(grid, config) {
    if (config.imagePath != null && config.imagePath != '')
        grid.setImagePath(config.imagePath);

    if (config.skin != null && config.skin != '')
        grid.setSkin(config.skin)

    if (config.enableAutoHeight != null && config.enableAutoHeight != '')
        grid.enableAutoHeigth(config.enableAutoHeight.mode, config.enableAutoHeight.maxHeight, config.enableAutoHeight.countFullHeight);

    if (config.enableAutoWidth != null && config.enableAutoWidth != '')
        grid.enableAutoWidth(config.enableAutoWidth.mode, config.enableAutoWidth.maxLimit, config.enableAutoWidth.minLimit);

    if (config.enableEditEvents != null && config.enableEditEvents != '')
        grid.enableEditEvents(config.enableEditEvents.click, config.enableEditEvents.dblclick, config.enableEditEvents.f2Key);

    if (config.header != null && config.header != '') {
        if (config.headerStyle != null && config.headerStyle != '') {
            grid.setHeader(config.header, null, config.headerStyle);
        } else {
            grid.setHeader(config.header);
        }
    }
    if (config.header2 != null && config.header2 != '') {
        if (config.headerStyle2 != null && config.headerStyle2 != '') {
            grid.attachHeader(config.header2, config.headerStyle2);
        } else {
            grid.attachHeader(config.header2);
        }
    }

    if (config.colTypes != null && config.colTypes != '')
        grid.setColTypes(config.colTypes);

    if (config.initWidthsP != null && config.initWidthsP != '')
        grid.setInitWidthsP(config.initWidthsP);

    if (config.initWidths != null && config.initWidths != '')
        grid.setInitWidths(config.initWidths);

    if(config.colAlign != null && config.colAlign != '')
        grid.setColAlign(config.colAlign);

    if (config.colSorting != null && config.colSorting != '')
        grid.setColSorting(config.colSorting);

    if (config.colValidators != null && config.colValidators != '') {
        grid.enableValidation(true);
        grid.setColValidators(config.colValidators);
        grid.attachEvent('onValidationError', function (id, ind, value) { onErrorGrid(grid, id, ind, value); });
    }

    if (config.colFilter != null && config.colFilter != '')
        grid.attachHeader(config.colFilter);

    if (config.enableDistributedParsing != null && config.enableDistributedParsing != '')
        grid.enableDistributedParsing(config.enableDistributedParsing.mode, config.enableDistributedParsing.count, config.enableDistributedParsing.time);

    if (config.footer != null && config.footer != '') {
        if (config.footerStyle != null)
            grid.attachFooter(config.footer, config.footerStyle);
        else
            grid.attachFooter(config.footer);
    }

    if (config.footers != null) {
        for (var i = 0; i < config.footers.length; i++) {
            var footer = config.footers[i];
            if (config.footersStyle != null){
                var footerStyle = config.footersStyle[i];
                grid.attachFooter(footer, footerStyle);
            }
            else{
                grid.attachFooter(footer);
            }
        }
    }
 
    if (config.colHidden != null && config.colHidden != '')
        grid.setColumnsVisibility(config.colHidden);

    if (config.enableEditEvents != null)
        grid.enableEditEvents(config.enableEditEvents.click, config.enableEditEvents.dblclick, config.enableEditEvents.f2Key);

    if (config.SetNumberFormat != null && config.SetNumberFormat != '' && grid.setNumberFormat != null) {
        for (var i = 0; i < config.SetNumberFormat.length; i++) {
            grid.setNumberFormat(config.SetNumberFormat[i][0], config.SetNumberFormat[i][1], config.SetNumberFormat[i][2], config.SetNumberFormat[i][3]);
        }
    }
}

function selectGridRow(cell) {
    var rowId = cell.parentNode.idd;
    cell.parentNode.grid.selectRowById(rowId, false, true, false);
    return rowId;
}

/**
*Limpia los filtros de la grid 
*@param {Object} grid objeto dhtmlXGridFromTable grid  
*/
function clearGridFilter(grid) {
    if (grid.filterBy == undefined)
        return;
    grid.filterBy(0, "");
    grid._f_rowsBuffer = null;
}

/**
*Remueve una celda especifica 
*@param {HTMLTableCellElement} cell objeto de la celda   
*@returns {String} rowId de la fila removida
*/
function removeGridRowCell(cell, cb, min) {
    return removeGridRow(cell.parentNode.grid, cell.parentNode.idd, cb, min);
}

/**
*Remueve una fila especifica 
*@param {Object} grid objeto dhtmlXGridFromTable grid  
*@param {String} id indice de la fila 
*@param {Function} cb función de callback luego de eliminar la fila 
*@param {Integer} min número de filas mínimo que debe tener la grid
*@returns {Boolean} true al remover la fila
*/
function removeGridRow(grid, id, cb, min) {
    if (min == undefined) { min = 1; }
    if (grid.getRowsNum() == min) { return; }

    if (!confirm('Desea borrar la fila?'))
        return false;

    grid.deleteRow(id);
    grid.setSizes();

    if (cb != undefined && cb != null) { cb(id); }
    return true;
}

/**
*Agrega una fila a la grid 
*@param {Object} grid objeto dhtmlXGridFromTable grid  
*@param {String} id id de la fila 
*@param {String} idx indice que se le desea asignar a la nueva fila  
*@param {Array} arrAddRow conjunto de  valores de las celdas que se desean  incluir 
*/
function addGridRow(grid,id, idx, arrAddRow) {
    if (id != null)
        idx = grid.getRowIndex(id) + 1;

    clearGridFilter(grid);

    var newId = (new Date()).valueOf();

    if (idx == null)
        idx = grid.getRowsNum();

    //Para evitar ids repetidos cuanso se hace sobre un ciclo
    newId += grid.getRowsNum();

    grid.addRow(newId, arrAddRow, idx);

    return newId;
}

/**
*Se le agrega a una fila determinado numero de celdas 
*@param {HTMLTableCellElement} cell objeto de la celda
*@param {Array} arrAddRow Conjunto de valores de las celdas que se desean incluir
*@returns {String} RowId de la nueva fila
*/
function addGridRowCell(cell, arrAddRow) {
    return addGridRow(cell.parentNode.grid, cell.parentNode.idd, null, arrAddRow);
}

/**
*Se validan todos los campos dentro de la grid 
*@param {Object} grid objeto dhtmlXGridFromTable grid 
*@param {Object} colEnlazada objeto con columnas enlazadas
*@returns {Int} Número de errores generados
*/
function validateGrid(grid, colEnlazada) {
    var iError = 0;
    var StrErr = '';

    try{
        grid.forEachRow(
            function (id) {
                grid.forEachCell(id, function (cellObj, ind) {
                    if (grid.cells(id, ind) == null)
                        return;

                    if (grid.cells(id, ind).cell._cellType === "txt") {
                        var valTxt = validarTxtGrid(grid, id, ind);
                        if (valTxt[0] > 0) {
                            iError++;
                            StrErr += valTxt[1];
                        }
                    }
                    else if (grid.cells(id, ind).cell._cellType == undefined && grid.getColType(ind) === "txt") {
                        var valTxt = validarTxtGrid(grid, id, ind);
                        if (valTxt[0] > 0) {
                            iError++;
                            StrErr += valTxt[1];
                        }
                    }

                    grid.cells(id, ind).cell.className = ' ';

                    var validateCol = grid._validators.data[ind];
                    var validateCell = grid.cells(id, ind).getAttribute('validate');
                    if ((validateCol == null && (typeof (validateCell) == 'undefined' || validateCell == null || validateCell == ''))
                        || (validateCol != null && validateCell == '')) {
                        return;
                    }

                    var errorCell = grid.validateCell(id, ind);
                    if (!errorCell) {
                        iError++;
                        if (typeof (colEnlazada) != 'undefined' && colEnlazada != null) {
                            if (colEnlazada[ind] != null) {
                                onErrorGrid(grid, id, colEnlazada[ind], '');
                            }
                        }
                        if (iError < 10) {
                            var fila = parseInt(grid.getRowIndex(id)) + 1;
                            var value = grid.cells(id, ind).getValue();
                            StrErr += 'La Columna "' + grid.getColumnLabel(ind, 0) + '" en la Fila ' + fila + ' no puede ser ' + ((value == '') ? 'Vacía' : value) + '\n';
                        }
                    }
                });
            });
    } catch (E) { }

    if (iError > 0) {
        if (dhtmlx && dhtmlx.alert) {
            dhtmlx.alert(StrErr.replace(/\n/, '<br/>'));
        } else {
            alert(StrErr);
        }
    }

    grid.setSizes();
    return iError;
}

function onErrorGrid(grid, id, ind, value) {
    grid.cells(id, ind).cell.className += " dhtmlx_validation_error";
    return false;
}

/**
*Se toma el html y se asigna como valor  
*@param {Object} grid objeto dhtmlXGridFromTable grid  
*@param {Array} columns conjunto de indices de las columnas 
*/
function putGridCellHTMLtoValue(grid, columns) {
    grid.forEachRow(function (id) {
        for (var i = 0; i < columns.length; i++) {
            var value = grid.cells(id, columns[i]).cell.innerHTML;
            grid.cells(id, columns[i]).setValue(value);
        }
    });
}

/**
*Agrega Opciones a un Select   
*@param combo {element} elemento Select 
*@param options {Array}  conjunto de option a colocar 
*/
function setGridCombo(combo, options) {
    for (var i = 0; i < options.length; i += 2) {
        combo.put(options[i], options[i + 1]);
    }
    combo.save();
}

/**
*Llena un Select apartir de un Datatable
*@param {element} combo elemento Select 
*@param {Object} data dataTable 
*@param {String} fieldId id de la fila que lo contiene 
*@param {String} fields datos separados por comas 
*@param {String} formatOption formato como deseamos mostrar los datos 
*/
function setGridComboDB(combo, data, fieldId, fields, formatOption) {
    var arrFields = fields.split(',');
    for (var iOption = 0; iOption < data.length; iOption++) {
        var arrFieldValue = [];
        for (var iField = 0; iField < arrFields.length; iField++) {
            arrFieldValue.push(data[iOption][arrFields[iField]]);
        }
        var txtOption = formatOption.formatArray(arrFieldValue);
        combo.put(data[iOption][fieldId], txtOption);
    }
    combo.save();
}

function viewGridAllCols(grid, visible, cols) {
    for (var i = 0; i < grid.getColumnsNum(); i++) {
        grid.setColumnHidden(i, !visible);
    }
}

function configurarCalendario(grid) {
    dhtmlXCalendarObject.prototype.langData["es"] = {
        //date format
        dateformat: '%d.%m.%Y',
        //full names of months
        monthesFNames: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"],
        //shortened names of months
        monthesSNames: ["Ene", "Feb", "Maar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"],
        //full names of days
        daysFNames: ["Domingo", "Lunes", "Martes", "Miercoles", "Jueves", "Viernes", "Sabado"],
        //shortened names of days
        daysSNames: ["Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa"],
        //starting day of a week. Number from 1(Monday) to 7(Sunday)
        weekstart: 1
    }

    if (grid._grid_calendarA != undefined) {
        //Lenguaje español
        grid._grid_calendarA.loadUserLanguage("es");
        grid._grid_calendarA.hideTime();
    }
}

/**
*Validación simple de la grid
*@param {Object} grid dhtmlXGridFromTable grid a la cual pertenecen las columnas  
*@returns {Boolean} true si tiene errores, false si no los tiene
*/
function validarGrid(grid) {
    if (grid != null) {
        var errores = validateGrid(grid);
        return errores > 0;
    }
    return false;
}

function validarTxtGrid(grid, rowId, cId) {
    
    var valAlphaChar = /[^a-zA-ZÑñáÁéÉíÍóÓúÚ,|°¬`^\\\[\]\{\};:¨*´"#?¿!¡%\s\.\-\@\/\=\(\)\$\_\+\0x0d\d\t\n\r\f\v ]/g;
    var valor = grid.cells(rowId, cId).getValue().removeAccentsUpper();

    var str = "";
    var error = 0;

    if (valor.match(valAlphaChar)) {
        var fila = parseInt(grid.getRowIndex(rowId)) + 1;
        str = 'La Columna "' + grid.getColumnLabel(cId, 0) + '" en la Fila '
            + fila + " contiene caracteres invalidos\n";
        error = 1;
    }

    return [error, str];
}

/**
*Descargar Archivo de Excel genericamente para cualquier grid
*@param {Object} grid dhtmlXGridFromTable objeto de la grid inicializada
*@param {Object} cfgGrid Objeto de configuración de la grid
*@param {Boolean} incliur enviar en falso si desea no incluir las columnas del siguiente parámetro (esta al revés por error)
*@param {Array} cols Arreglo de enteros con los indices de las columnas a excluir
*@param {Array} colsNumericas Arreglo con indices de las columnas que son de tipo Moneda
*@param {Array} separadorDecimal Caracter con el separador decimal (, o .)
*@param {String} nombre Nombre del Archivo a generar
*@param {String} nombreHoja Nombre de la Hoja principal
*@param {String} idCargando Id de la imagen que esta mostrando que se esta generando el archivo
*@param {Boolean} rSepDecimal Indica si se desea reemplazar el valor de la columna con el separador decimal (Opcional)
*@param {Array} colsLink Arreglo de enteros con los indices de las columnas que serían tomadas como Links
*@param {Function} fnCb Función que se desea invocar cuando se genere el archivo en el servidor (Opcional)
*/
function generarExcelGrid(grid, cfgGrid, incliur, cols, colsNumericas, separadorDecimal, nombre, nombreHoja, idCargando, rSepDecimal, colsLink, fnCb) {
    if (idCargando != null || idCargando != '')
        setDisplayElements(true, idCargando);

    var params = getParamsExcelGrid(grid, cfgGrid, incliur, cols, colsNumericas, separadorDecimal, nombre, nombreHoja, rSepDecimal, colsLink);

    ajax_plantillas.ajaxMethodStr('ajax_generales.generarExcelGridSinFormato', params, function (data) {
        if (idCargando != null || idCargando != '')
            setDisplayElements(false, idCargando);

        if (data == null || data.value == null || data.value == '') {
            alert('Ocurrio un error al Generar el Archivo');
            return;
        }

        var ruta = data.value;
        var arrRuta = ruta.split('/');

        var a = document.createElement('a');
        a.target = '_blank';
        a.download = arrRuta[arrRuta.length - 1];
        a.href = ruta;

        try {
            document.childNodes[1].appendChild(a);
        } catch (E) {
            document.childNodes[0].appendChild(a);
        }

        if (fnCb) {
            fnCb(a, ruta);
        } else {
            a.click();
        }
    });
}

function getParamsExcelGrid(grid, cfgGrid, incliur, cols, colsNumericas, separadorDecimal, nombre, nombreHoja, rSepDecimal, colsLink) {
    if (colsLink == null)
        colsLink = [];

    var xml = '';
    var iRow = 0;
    var iRows = grid.getRowsNum();
    var arrEncabezados = cfgGrid.header.split(',');
    var arrEncabezadosOk = new Array();
    var arrColsNum = new Array();

    if (colsNumericas != undefined && colsNumericas != null) {
        for (var i = 0; i < colsNumericas.length; i++)
            arrColsNum.push(colsNumericas[i].toString());
    }

    if (cols.length == 0)
        cols = addColsGrid(grid, null, false);
    else if (!incliur)
        cols = addColsGrid(grid, cols, true);

    for (var iRow = 0; iRow < iRows; iRow++) {
        xml += "<r id='" + iRow + "'>";
        for (var j = 0; j < cols.length; j++) {
            var valor = '';

            try {
                //Para guardar el innerHTML en vez del valor
                if (grid.colsIH != null && grid.colsIH[cols[j]] != null) {
                    valor = grid.cells2(iRow, cols[j]).cell.innerHTML;
				}
				else {
                    valor = grid.cells2(iRow, cols[j]).getValue();
				}

				if (grid.replaceAcheck) {
                    if (grid.getColType(j) == 'acheck' || grid.getColType(j) == 'ch') {
						if (valor == 1)
							valor = 'SI';
						else
							valor = 'NO';
					}
				}

                if (valor.indexOf('href') !== -1) {
                    valor = grid.cells2(iRow, cols[j]).cell.childNodes[0].href;
                }

                if (rSepDecimal != null && rSepDecimal != undefined) {
                    if (rSepDecimal && arrColsNum.join().indexOf(cols[j]) != -1) {
                        if (separadorDecimal == '.')
                            valor = valor.replace(',', '.');
                        else
                            valor = valor.replace('.', ',');
                    }
                }

                xml += '<c>' + valor + '</c>';
                if (iRow == 0)
                    arrEncabezadosOk.push(arrEncabezados[cols[j]]);
            } catch (E) {
                console.error('Error: ', E);
            }
        }

        xml += '</r>';
    }

    var params = [xml, cfgGrid.initWidths, arrEncabezadosOk.join(), nombre, nombreHoja, arrColsNum.join(), separadorDecimal, colsLink.join()];
    return params;
}

function addColsGrid(grid, cols, excluir) {
    var colsOK = new Array();

    for (var i = 0; i < grid.getColumnsNum() ; i++) {
        if (excluir) {
            if (cols.indexOf(i) == -1)
                colsOK.push(i);
        } else {
            colsOK.push(i);
        }
    }

    return colsOK;
}

function getGridXmlFormato(numCols) {
    var fRow = '<r id="{0}">';

    for (var i = 1; i <= numCols; i++)
        fRow += '<c>{' + i + '}</c>';

    fRow += '</r>'
    return fRow;
}

function addAcheckValores(grid, arrCols, arrValores) {
    for (var i = 0; i < arrCols.length; i++) {
        grid['ack' + arrCols[i] + '0'] = arrValores[i][0];
        grid['ack' + arrCols[i] + '1'] = arrValores[i][1];
    }
}

function addAcheck3Valores(grid, arrCols, arrValores) {
    for (var i = 0; i < arrCols.length; i++) {
        grid['ack' + arrCols[i] + '0'] = arrValores[i][0];
        grid['ack' + arrCols[i] + '1'] = arrValores[i][1];
        grid['ack' + arrCols[i] + '2'] = arrValores[i][2];
    }
}

function setColValue(grid, col, value) {
    grid.forEachRow(
        function (id) {
            if (grid.cells(id, col).value) {
                grid.cells(id, col).value = value;
            }
            else {
                grid.cells(id, col).setValue(value);
            }
        });
}
function setColHTML(grid, col, value) {
    grid.forEachRow(
        function (id) {
            grid.cells(id, col).cell.innerHTML = value;
        });
}

/**
*Descargar Archivo en PDF genericamente para cualquier grid
*@param {Object} grid dhtmlXGridFromTable objeto de la grid inicializada
*@param {Object} cfgGrid Objeto de configuración de la grid
*@param {Boolean} incliur enviar en falso si desea no incluir las columnas del siguiente parámetro (esta al revés por error)
*@param {Array} cols Arreglo de enteros con los indices de las columnas a excluir
*@param {Array} colsNumericas Arreglo con indices de las columnas que son de tipo Moneda
*@param {Array} separadorDecimal Caracter con el separador decimal (, o .)
*@param {String} nombre Nombre del Archivo a generar
*@param {String} nombreHoja Nombre de la Hoja principal
*@param {String} idCargando Id de la imagen que esta mostrando que se esta generando el archivo
*@param {Boolean} rSepDecimal Indica si se desea reemplazar el valor de la columna con el separador decimal (Opcional)
*@param {Array} colsLink Arreglo de enteros con los indices de las columnas que serían tomadas como Links
*@param {Function} fnCb Función que se desea invocar cuando se genere el archivo en el servidor (Opcional)
*/
function generarPdfGrid(grid, cfgGrid, incliur, cols, colsNumericas, separadorDecimal, nombre, nombreHoja, idCargando, rSepDecimal, colsLink, fnCb) {
    if (idCargando != null || idCargando != '')
        setDisplayElements(true, idCargando);

    var paramsExcel = getParamsExcelGrid(grid, cfgGrid, incliur, cols, colsNumericas, separadorDecimal, nombre, '', rSepDecimal, colsLink);
    var params = [paramsExcel[0], paramsExcel[2], nombre, nombreHoja];

    ajax_plantillas.ajaxMethodStr('ajax_generales.generarPdfGrid', params, function (data) {
        if (idCargando != null || idCargando != '')
            setDisplayElements(false, idCargando);

        if (data == null || data.value == null || data.value == '') {
            alert('Ocurrio un error al Generar el Archivo');
            return;
        }

        var ruta = data.value;
        var arrRuta = ruta.split('/');

        var a = document.createElement('a');
        a.target = '_blank';
        a.download = arrRuta[arrRuta.length - 1];
        a.href = ruta;

        try {
            document.childNodes[1].appendChild(a);
        } catch (E) {
            document.childNodes[0].appendChild(a);
        }

        if (fnCb) {
            fnCb(a, ruta);
        } else {
            a.click();
        }
    });
}