Export multiple row headers

Export multiple row headers

lisarushlisarush Posts: 85Questions: 15Answers: 0
edited July 2014 in Free community support

After not finding a suitable answer/solution to the problem of TableTools only exporting 1 row of TH (header) data,
I implemented the following code which handles exporting <thead>s with multiple rows. It properly handles TH cells
with both "rowspan" and "colspan" values. Since the export is simply a CSV file and does not support merged cells,
the export will add empty cells to the generated CSV output to "fill in" the space. After the export file is generated,
the user can easily do a "merge cells" operation within Excel if desired.

Note that I am not a JavaScript programmer, so there may be a more efficient way to write this, but it works for me.
Maybe it will help someone else.

First, I added the following function:

/* ----- BEGIN added code ----- */          
    "_fnGetHeaders": function() {
        var dt = this.s.dt;
        var thRows = dt.nTHead.rows;
        var numRows = thRows.length;
        var matrix = [];

        // Iterate over each row of the header and add information to matrix.
        for ( var rowIdx = 0;  rowIdx < numRows;  rowIdx++ ) {
            var $row = $(thRows[rowIdx]);

            // Iterate over actual columns specified in this row.
            var $ths = $row.children("th");
            for ( var colIdx = 0;  colIdx < $ths.length;  colIdx++ )
            {
                var $th = $($ths.get(colIdx));
                var colspan = $th.attr("colspan") || 1;
                var rowspan = $th.attr("rowspan") || 1;
                var colCount = 0;
             
                // ----- add this cell's title to the matrix
                if (matrix[rowIdx] === undefined) {
                    matrix[rowIdx] = [];  // create array for this row
                }
                // find 1st empty cell
                for ( var j = 0;  j < (matrix[rowIdx]).length;  j++, colCount++ ) {
                    if ( matrix[rowIdx][j] === "PLACEHOLDER" ) {
                        break;
                    }
                }
                var myColCount = colCount;
                matrix[rowIdx][colCount++] = $th.text();
            
                // ----- If title cell has colspan, add empty titles for extra cell width.
                for ( var j = 1;  j < colspan;  j++ ) {
                    matrix[rowIdx][colCount++] = "";
                }
             
                // ----- If title cell has rowspan, add empty titles for extra cell height.
                for ( var i = 1;  i < rowspan;  i++ ) {
                    var thisRow = rowIdx+i;
                    if ( matrix[thisRow] === undefined ) {
                        matrix[thisRow] = [];
                    }
                    // First add placeholder text for any previous columns.                 
                    for ( var j = (matrix[thisRow]).length;  j < myColCount;  j++ ) {
                        matrix[thisRow][j] = "PLACEHOLDER";
                    }
                    for ( var j = 0;  j < colspan;  j++ ) {  // and empty for my columns
                        matrix[thisRow][myColCount+j] = "";
                    }
                }
            }
        }
       
        return matrix;
    },
/* ----- END added code ----- */            

Then, modified the following section of "_fnGetDataTablesData":

        if ( oConfig.bHeader )
        {
/* ----- BEGIN changed Code ----- */            
            var headerMatrix = this._fnGetHeaders();
            for ( var rowIdx = 0;  rowIdx < headerMatrix.length;  rowIdx++ ) {
                aRow = [];
                for ( var colIdx = 0;  colIdx < (headerMatrix[rowIdx]).length;  colIdx++ ) {
                    sLoopData = headerMatrix[rowIdx][colIdx].replace(/\n/g," ").replace( /<.*?>/g, "" ).replace(/^\s+|\s+$/g,"");
                    sLoopData = this._fnHtmlDecode( sLoopData );

                    aRow.push( this._fnBoundData( sLoopData, oConfig.sFieldBoundary, regex ) );
                }
                aData.push( aRow.join(oConfig.sFieldSeperator) );
            }
/* ----- END changed Code ----- */
        }

Replies

  • lisarushlisarush Posts: 85Questions: 15Answers: 0
    edited July 2014

    Posted again with better code sections.

        /* ----- BEGIN added Code ----- */          
        "_fnGetHeaders": function() {
            var dt = this.s.dt;
            var thRows = dt.nTHead.rows;
            var numRows = thRows.length;
            var matrix = [];
    
            // Iterate over each row of the header and add information to matrix.
            for ( var rowIdx = 0;  rowIdx < numRows;  rowIdx++ ) {
                var $row = $(thRows[rowIdx]);
    
                // Iterate over actual columns specified in this row.
                var $ths = $row.children("th");
                for ( var colIdx = 0;  colIdx < $ths.length;  colIdx++ )
                {
                    var $th = $($ths.get(colIdx));
                    var colspan = $th.attr("colspan") || 1;
                    var rowspan = $th.attr("rowspan") || 1;
                    var colCount = 0;
                 
                    // ----- add this cell's title to the matrix
                    if (matrix[rowIdx] === undefined) {
                        matrix[rowIdx] = [];  // create array for this row
                    }
                    // find 1st empty cell
                    for ( var j = 0;  j < (matrix[rowIdx]).length;  j++, colCount++ ) {
                        if ( matrix[rowIdx][j] === "PLACEHOLDER" ) {
                            break;
                        }
                    }
                    var myColCount = colCount;
                    matrix[rowIdx][colCount++] = $th.text();
                
                    // ----- If title cell has colspan, add empty titles for extra cell width.
                    for ( var j = 1;  j < colspan;  j++ ) {
                        matrix[rowIdx][colCount++] = "";
                    }
                 
                    // ----- If title cell has rowspan, add empty titles for extra cell height.
                    for ( var i = 1;  i < rowspan;  i++ ) {
                        var thisRow = rowIdx+i;
                        if ( matrix[thisRow] === undefined ) {
                            matrix[thisRow] = [];
                        }
                        // First add placeholder text for any previous columns.                 
                        for ( var j = (matrix[thisRow]).length;  j < myColCount;  j++ ) {
                            matrix[thisRow][j] = "PLACEHOLDER";
                        }
                        for ( var j = 0;  j < colspan;  j++ ) {  // and empty for my columns
                            matrix[thisRow][myColCount+j] = "";
                        }
                    }
                }
            }
           
            return matrix;
        },
        /* ----- END added Code ----- */            
    

    Modified the following section of "_fnGetDataTablesData":

            if ( oConfig.bHeader )
            {
        /* ----- BEGIN changed Code ----- */            
                var headerMatrix = this._fnGetHeaders();
                for ( var rowIdx = 0;  rowIdx < headerMatrix.length;  rowIdx++ ) {
                    aRow = [];
                    for ( var colIdx = 0;  colIdx < (headerMatrix[rowIdx]).length;  colIdx++ ) {
                        sLoopData = headerMatrix[rowIdx][colIdx].replace(/\n/g," ").replace( /<.*?>/g, "" ).replace(/^\s+|\s+$/g,"");
                        sLoopData = this._fnHtmlDecode( sLoopData );
    
                        aRow.push( this._fnBoundData( sLoopData, oConfig.sFieldBoundary, regex ) );
                    }
                    aData.push( aRow.join(oConfig.sFieldSeperator) );
                }
        /* ----- END changed Code ----- */          
            }
    
  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    Hi,

    Thanks very much for this - I'm sure others will find it of great benefit as this has come up a couple of times before!

    Regards,
    Allan

  • rpaixaorpaixao Posts: 1Questions: 0Answers: 0

    This piece of code is really usefull. Thanks a lot !

This discussion has been closed.