DataTables row details information not appearing in TableTools PDF and XLS export

DataTables row details information not appearing in TableTools PDF and XLS export

rxm023rxm023 Posts: 2Questions: 1Answers: 0

I am using Datatables (v 1.10.2) and TableTools (v 2.2.3) to render a report. The main row has aggregate data for categories and subcategories. The row expands on click event as explained in example (https://datatables.net/examples/api/row_details.html) and displays details about category and subcategory in HTML table layout. One of the business requirement is to be able to export data in PDF and XLS format. We are using TableTools actively in entire application, but in aforementioned use case TableTools just exports row data. Row details/Child row data is missing from export even though they appear on screen.

I tried deferRender:true but it does not seem related to issue. Is there a callback I can use to make sure that row and row details/child row data gets exported in PDF and XLS format as shown in example (https://datatables.net/examples/api/row_details.html)? Our product stake holders like the performance of datatables for this use case and would like to use it for other reports in application.

Please feel free to send a note in case of any additional questions.

Answers

  • robynleighpetersonrobynleighpeterson Posts: 1Questions: 0Answers: 0

    I had the same issue. I had to override the _fnGetDataTablesData function. To start I added the call to my function into the column definition.

    "aButtons": [
        {
        "sExtends": "xls",
        "sButtonText": exportButton,
        "fnClick": function (nButton, oConfig, flash) {
            this.fnSetText(flash, exportMyTable(oConfig, this, childRows));
        }
    

    I ended up passing my header rows (the dataTable) and my child row JSON data separately. The rows in my table are organized by different product types.

    function exportMyTable(oConfig, myDataTable, childRows)
    {
        var i, iLen, j, jLen, k;
        var aRow, aData=[], sLoopData='', arr;
        var dt = myDataTable.s.dt, tr, child;
        var regex = "/(?:/g";
        var aColumnsInc = myDataTable._fnColumnTargets(oConfig.mColumns);
        var header = []; // if child row header is different that parent row header
    
        /*
        * Header
        */
        if (oConfig.bHeader) {
            for (i = 0, iLen = dt.aoColumns.length ; i < iLen ; i++) {
                if (aColumnsInc[i]) {
                    sLoopData = dt.aoColumns[i].sTitle.replace(/\n/g, " ").replace(/<.*?>/g, "").replace(/^\s+|\s+$/g, "");
                    sLoopData = myDataTable._fnHtmlDecode(sLoopData);
                
                    header.push(myDataTable._fnBoundData(sLoopData, oConfig.sFieldBoundary, regex));
                }
            }
        }
    
        /*
        * Body
        */
        var aDataIndex;
    
        if (DataTable.Api) {
            // 1.10+ style
            aDataIndex = new DataTable.Api(dt)
                .rows(oConfig.oSelectorOpts)
                .indexes()
                .flatten()
                .toArray();
        }
        else {
            // 1.9- style
            aDataIndex = dt.oInstance
                .$('tr', oConfig.oSelectorOpts)
                .map(function (id, row) {
                    return dt.oInstance.fnGetPosition(row);
                })
                .get();
        }
        var currentProduct = ''; 
        for (j = 0, jLen = aDataIndex.length ; j < jLen ; j++) 
        {
            aData.push(header.join(oConfig.sFieldSeperator)); // push title row for each header row
            tr = dt.aoData[aDataIndex[j]].nTr;
            aRow = [];
    
            /* Columns */
            for (i = 0, iLen = dt.aoColumns.length ; i < iLen ; i++) {
                if (aColumnsInc[i]) {
                    /* Convert to strings (with small optimisation) */
                    var mTypeData = dt.oApi._fnGetCellData(dt, aDataIndex[j], i, 'display');
                    if (oConfig.fnCellRender) {
                        sLoopData = oConfig.fnCellRender(mTypeData, i, tr, aDataIndex[j]) + "";
                    }
                    else if (typeof mTypeData == "string") {
                        /* Strip newlines, replace img tags with alt attr. and finally strip html... */
                        sLoopData = mTypeData.replace(/\n/g, " ");
                        sLoopData = sLoopData.replace(/<img.*?\s+alt\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s>]+)).*?>/gi, '$1$2$3');
                        sLoopData = sLoopData.replace(/<.*?>/g, "");
                    }
                    else {
                        sLoopData = mTypeData + "";
                    }
    
                    /* Trim and clean the data */
                    sLoopData = sLoopData.replace(/^\s+/, '').replace(/\s+$/, '');
                    sLoopData = myDataTable._fnHtmlDecode(sLoopData);
                    // get the current product from it's column to later get corresponding child data
                    if(i == 1){ 
                        currentProduct = sLoopData;
                    }
    
                    /* Bound it and add it to the total data */
                    aRow.push(myDataTable._fnBoundData(sLoopData, oConfig.sFieldBoundary, regex));
                }
            }
    
            aData.push(aRow.join(oConfig.sFieldSeperator));
    
            /* Get all details rows */
            if (childRows != null) {
                // push child title/header row
                aRow = [];
                aRow.push("Header 1");
                aRow.push("Header 2");
                aRow.push("Header 3");
                aData.push(aRow.join(oConfig.sFieldSeperator));
    
                k = 0;
                // loop through all child data and push only that which corresponds with the current product
                while (k < childRows.value.length) { 
                    if (childRows.value[k].VARIABLE1 === currentProduct) {
                        aRow = [];
                        aRow.push(childRows.value[k].VARIABLE2);
                        aRow.push(childRows.value[k].VARIABLE3);
                        aRow.push(childRows.value[k].VARIABLE4);
                        aData.push(aRow.join(oConfig.sFieldSeperator));
                        k++;
                    }
                    else {
                        k++;
                    }
                }
            }
        }
    
        /*
        * Footer
        */
        if (oConfig.bFooter && dt.nTFoot !== null) {
            aRow = [];
    
            for (i = 0, iLen = dt.aoColumns.length ; i < iLen ; i++) {
                if (aColumnsInc[i] && dt.aoColumns[i].nTf !== null) {
                    sLoopData = dt.aoColumns[i].nTf.innerHTML.replace(/\n/g, " ").replace(/<.*?>/g, "");
                    sLoopData = myDataTable._fnHtmlDecode(sLoopData);
    
                    aRow.push(myDataTable._fnBoundData(sLoopData, oConfig.sFieldBoundary, regex));
                }
            }
    
            aData.push(aRow.join(oConfig.sFieldSeperator));
        }
    
        var _sLastData = aData.join(myDataTable._fnNewline(oConfig));
        return _sLastData;
    }
    

    I hope this helps.

  • felixkirathefelixkirathe Posts: 1Questions: 0Answers: 0

    Hello Peterson,

    I trust you doing well. In this article

    You have used a variable childRows. Where are you getting its contents?

    Regards,
    Felix

This discussion has been closed.