How to export all rows from Datatables using Ajax?

前端 未结 12 1147
广开言路
广开言路 2020-11-29 23:38

I am using new feature in Datatables: \"HTML5 export buttons\". I am loading data with Ajax.

https://datatables.net/extensions/buttons/examples/html5/simple.html

相关标签:
12条回答
  • 2020-11-29 23:47

    Just wanted to post an actual answer for people struggling with this.

    If you are exporting using the excel button, you can use the customizeData button property to format the data going to excel a moment before it exports.

    I used this to make a synchronous api call to my server to get the data, return it, massage it, and then let it continue on it's way. Code below.

                               {
                    extend: 'excel',
                    customizeData: function (p)
                    {
                        //get the params for the last datatables ajax call
                        var params = JSON.parse(options.dataTable.ajax.params());
                        //flag to tell the server to ignore paging info and get everything that matches the filter
                        params.export = true;
                        UC.Api(options.api.read.getHook(), params, function (data)
                        {
                            p.body = new Array();
                            $.each(data.data, function (i, d)
                            {
                                var item = [d.serial, UC.FormatDateToLocal(d.meta.Date), d.transmission.title, d.transmission.type, d.transmission.information];
                                p.body.push(item);
                            });
                        }, null, { async: false });
                    }
                },
    
    0 讨论(0)
  • 2020-11-29 23:50

    If you use Laravel framework, you can use this....

    $.fn.DataTable.Api.register( 'buttons.exportData()', function( options ) {
      if(this.context.length) {
    
        var src_keyword = $('.dataTables_filter input').val();
    
        // make columns for sorting
        var columns = [];
        $.each(this.context[0].aoColumns, function(key, value) {
          columns.push({
            'data' : value.data, 
            'name' : value.name, 
            'searchable' : value.bSearchable, 
            'orderable' : value.bSortable
          });
        });
    
        // make option for sorting
        var order = [];
        $.each(this.context[0].aaSorting, function(key, value) {
          order.push({
            'column' : value[0], 
            'dir' : value[1]
          });
        });
    
        // make value for search
        var search = {
          'value' : this.context[0].oPreviousSearch.sSearch, 
          'regex' : this.context[0].oPreviousSearch.bRegex
        };
    
        var items = [];
        var status = $('#status').val();
        $.ajax({
          url: "server_side_url",
          data: { columns: columns, order: order, search: search, status: status, page: 'all' }
          success: function (result) {
    
            $.each(result.data, function(key, value) {
    
              var item = [];
    
              item.push(key+1);
              item.push(value.username);
              item.push(value.email);
              item.push(value.created_at);
              item.push(value.status);
    
              items.push(item);
            });
          },
          async: false
        });
    
        return {
          body: items, 
          // skip actions header
          header: $("#user_table thead tr th").map(function() { 
            if(this.innerHTML!='Actions')
              return this.innerHTML; 
          }).get()
        };
      }
    });
    
    var user_table = $('#user_table').DataTable({
      dom: 'Bfrtip',
      buttons: [
      'copy', 'csv', 'excel', 'pdf', 'print'
      ],
      "oSearch": {"bSmart": false},
      processing: true,
      serverSide: true,
      ajax: {
        url: "server_side_url",
        type: 'GET',
        data: function (d) {
          d.status = ""; // when onload make status as empty to get all users
        }
      },
      columns: [
      {data: 'DT_RowIndex', name: 'DT_RowIndex'},
      {data: 'username', name: 'username'},
      {data: 'email', name: 'email'},
      {data: 'created_at', name: 'created_at'},
      {data: 'status', name: 'status'},
      {data: 'actions', name: 'actions', orderable: false, searchable: false},
      ],
    });
    
    // filter users with status
    $('#status').change(function() {
      user_table.draw();
    });
    
    0 讨论(0)
  • 2020-11-29 23:52

    Yes, it's totally possible to make this work. Internally, DataTables has a function called buttons.exportData(). When you press a button, this function is called and returns the current page content. You can overwrite that function so it pulls all server side results based on current filters. And calling the same url used for ajax pagination.

    You overwrite it before initializing your table. The code is as follows:

    $(document).ready(function() {
    
        jQuery.fn.DataTable.Api.register( 'buttons.exportData()', function ( options ) {
                if ( this.context.length ) {
                    var jsonResult = $.ajax({
                        url: 'myServerSide.json?page=all',
                        data: {search: $(#search).val()},
                        success: function (result) {
                            //Do nothing
                        },
                        async: false
                    });
    
                    return {body: jsonResult.responseJSON.data, header: $("#myTable thead tr th").map(function() { return this.innerHTML; }).get()};
                }
            } );
    
        $("#myTable ").DataTable(
            {
                "dom": 'lBrtip',
                "pageLength": 5, 
                "buttons": ['csv','print', 'excel', 'pdf'],
                "processing": true,
                "serverSide": true,
                "ajax": {
                    "url": "myServerSide.json",
                    "type": 'GET',
                    "data": {search: $(#search).val()} 
                }
            }
    });
    
    0 讨论(0)
  • 2020-11-29 23:52

    I'm using Datatables Version: 1.10.15, and got @kevenpo's answer to work. I had to modify it a bit to handle our server-side parameters, but that was the only stumbling block. I changed his line: data.length = 2147483647; to data.params[2]= -1; because we stored our server-side parameters in a params sub-array. I have not tested it yet with a very large dataset to see what the performance is, but this is a very clever solution.

    0 讨论(0)
  • 2020-11-29 23:55

    Thanks a lot to the user "kevinpo". He has given the way how all records from jquery datatable to be downloaded as excel when server side processing is On. Based on his answer, here i have complete export functionality implemented (copy, excel, csv, pdf, print) for server side processing.

    inside $(document).ready() define the below function & call this function on action of each export button like below :

    /* For Export Buttons available inside jquery-datatable "server side processing" - Start
    - due to "server side processing" jquery datatble doesn't support all data to be exported
    - below function makes the datatable to export all records when "server side processing" is on */
    
    function newexportaction(e, dt, button, config) {
        var self = this;
        var oldStart = dt.settings()[0]._iDisplayStart;
        dt.one('preXhr', function (e, s, data) {
            // Just this once, load all data from the server...
            data.start = 0;
            data.length = 2147483647;
            dt.one('preDraw', function (e, settings) {
                // Call the original action function
                if (button[0].className.indexOf('buttons-copy') >= 0) {
                    $.fn.dataTable.ext.buttons.copyHtml5.action.call(self, e, dt, button, config);
                } else if (button[0].className.indexOf('buttons-excel') >= 0) {
                    $.fn.dataTable.ext.buttons.excelHtml5.available(dt, config) ?
                        $.fn.dataTable.ext.buttons.excelHtml5.action.call(self, e, dt, button, config) :
                        $.fn.dataTable.ext.buttons.excelFlash.action.call(self, e, dt, button, config);
                } else if (button[0].className.indexOf('buttons-csv') >= 0) {
                    $.fn.dataTable.ext.buttons.csvHtml5.available(dt, config) ?
                        $.fn.dataTable.ext.buttons.csvHtml5.action.call(self, e, dt, button, config) :
                        $.fn.dataTable.ext.buttons.csvFlash.action.call(self, e, dt, button, config);
                } else if (button[0].className.indexOf('buttons-pdf') >= 0) {
                    $.fn.dataTable.ext.buttons.pdfHtml5.available(dt, config) ?
                        $.fn.dataTable.ext.buttons.pdfHtml5.action.call(self, e, dt, button, config) :
                        $.fn.dataTable.ext.buttons.pdfFlash.action.call(self, e, dt, button, config);
                } else if (button[0].className.indexOf('buttons-print') >= 0) {
                    $.fn.dataTable.ext.buttons.print.action(e, dt, button, config);
                }
                dt.one('preXhr', function (e, s, data) {
                    // DataTables thinks the first item displayed is index 0, but we're not drawing that.
                    // Set the property to what it was before exporting.
                    settings._iDisplayStart = oldStart;
                    data.start = oldStart;
                });
                // Reload the grid with the original page. Otherwise, API functions like table.cell(this) don't work properly.
                setTimeout(dt.ajax.reload, 0);
                // Prevent rendering of the full data to the DOM
                return false;
            });
        });
        // Requery the server with the new one-time export settings
        dt.ajax.reload();
    };
    //For Export Buttons available inside jquery-datatable "server side processing" - End
    

    And for buttons, define like below

    "buttons": [
                               {
                                   "extend": 'copy',
                                   "text": '<i class="fa fa-files-o" style="color: green;"></i>',
                                   "titleAttr": 'Copy',                               
                                   "action": newexportaction
                               },
                               {
                                   "extend": 'excel',
                                   "text": '<i class="fa fa-file-excel-o" style="color: green;"></i>',
                                   "titleAttr": 'Excel',                               
                                   "action": newexportaction
                               },
                               {
                                   "extend": 'csv',
                                   "text": '<i class="fa fa-file-text-o" style="color: green;"></i>',
                                   "titleAttr": 'CSV',                               
                                   "action": newexportaction
                               },
                               {
                                   "extend": 'pdf',
                                   "text": '<i class="fa fa-file-pdf-o" style="color: green;"></i>',
                                   "titleAttr": 'PDF',                               
                                   "action": newexportaction
                               },
                               {
                                    "extend": 'print',
                                    "text": '<i class="fa fa-print" style="color: green;"></i>',
                                    "titleAttr": 'Print',                                
                                    "action": newexportaction
                               }
    ],
    

    That's it. Now your download is ready.

    0 讨论(0)
  • 2020-11-29 23:55

    I know this is an old question, however for anyone struggling with this, here's my solution.

    Variables:

    var downloading = false,
        downloadTimestamp = null;
    

    Download button definition:

    buttons: [{
        text: '<span class="glyphicon glyphicon-save-file" aria-hidden="true"></span>',
        titleAttr: 'CSV',
        className: 'downloadCSV',
        action: function(e, dt, node, config) {
            if (downloading === false) { //if download is in progress, do nothing, else
                node.attr('disabled', 'disabled'); //disable download button to prevent multi-click, probably some sort of *busy* indicator is a good idea
    
                downloading = true; //set downloading status to *true*
    
                dt.ajax.reload(); //re-run *DataTables* AJAX query with current filter and sort applied
            }
        }
    }]
    

    Ajax definition:

    ajax: {
        url: ajaxURL,
        type: 'POST',
        data: function(data) {
            data.timestamp = new Date().getTime(); //add timestamp to data to be sent, it's going to be useful when retrieving produced file server-side
    
            downloadTimestamp = data.timestamp; //save timestamp in local variable for use with GET request when retrieving produced file client-side
    
            if (downloading === true) { //if download button was clicked
                data.download = true; //tell server to prepare data for download
                downloading = data.draw; //set which *DataTable* draw is actually a request to produce file for download
            }
    
            return { data: JSON.stringify(data) }; //pass data to server for processing
        }
    }
    

    'preDrawCallback' function:

    preDrawCallback: function(settings) {
        if (settings.iDraw === downloading) { //if returned *DataTable* draw matches file request draw value
            downloading = false; //set downloading flag to false
    
            $('.downloadCSV').removeAttr('disabled'); //enable download button
    
            window.location.href = ajaxURL + '?' + $.param({ ts: downloadTimestamp }); //navigate to AJAX URL with timestamp as parameter to trigger file download. Or You can have hidden IFrame and set its *src* attribute to the address above.
    
            return false; //as it is file request, table should not be re-drawn
        }
    }
    

    Server-side:

    if(download == false), then server executes SELECT columns FROM tables WHERE rowNumber BETWEEN firstRow AND lastRow and outputs result for normal display within DataTable.

    if(download == true), then server executes SELECT columns FROM tables and stores all rows formatted as CSV file (or any other file format depending on what Your server environment is capable to produce) server-side for later retrieval by GET request.

    Following is ASP JScript code that I've used server-side:

        var timestamp = Number(Request.QueryString('ts')), //if it's a GET request, get timestamp
            tableData = {
                draw: data.draw,
                recordsTotal: 100, //some number static or dynamic
                recordsFiltered: 10, //some number static or dynamic
                data: []
            };
            jsonData = String(Request.Form('data')), //if it's POST request, get data sent by *DataTable* AJAX
            data = jsonData === 'undefined' || jsonData.length === 0 ? null : JSON.parse(jsonData); //do some error checking (optional)
    
        if(!isNaN(timestamp)) { //check timestamp is valid
            var csvTextKey = 'download-' + timestamp, //this is where timestamp value is used (can be any other unique value)
                csvText = Session(csvTextKey); //obtain saved CSV text from local server-side storage
    
            if(typeof csvText === 'undefined') { //if CSV text does not exist in local storage, return nothing (or throw error is You wish)
                Response.End();
            }
    
            //if CSV exists:
            Response.ContentType = 'text/csv'; //set response mime type
            Response.AddHeader('Content-Disposition', 'attachment; filename=test.csv'); //add header to tell browser that content should be downloaded as file and not displayed
    
            Response.Write(csvText); //send all content to browser
    
            Response.End(); //stop further server-side code execution
        }
    
        //if timestamp is not valid then we assume this is POST request, hence data should be either prepared for display or stored for file creation
    
        if(typeof data !== 'object' || data === null) { //do some more clever error checking
            throw 'data is not an object or is null';
        }
    
            var recordset = data.download === true ? sqlConnection.Execute('SELECT * FROM #FinalTable') : Utilities.prepAndRunSQLQuery('SELECT * FROM #FinalTable WHERE rowId BETWEEN ? AND ?', [data.start, data.start + data.length], //execute SELECT either for display or for file creation
                headerRow = [],
                sqlHeaderRow = [],
                exportData = [];; 
    
            if(data.download === true) { //create CSV file (or any other file)
                if(!Array.isArray(data.columns)) {
                    throw 'data.columns is not an array';
                }
    
                for(var i = 0, dataColumnsCount = data.columns.length; i < dataColumnsCount; ++i) {
                    var dataColumn = data.columns[i], //get columns data object sent by client
                        title = dataColumn.title, //this is custom property set on client-side (not shown in code above)
                        sqlColumnName = typeof dataColumn.data === 'string' ? dataColumn.data : (typeof dataColumn.data.display === 'string' ? dataColumn.data.display : dataColumn.data['_']); //set SQL table column name variable
    
                    if(typeof title === 'string' && typeof sqlColumnName === 'string' && columnNames.indexOf(sqlColumnName) > -1) { //some more error checking
                        headerRow.push(title);
                        sqlHeaderRow.push(sqlColumnName);
                    }
                }
    
                exportData.push('"' + headerRow.join('","') + '"'); //add table header row to in CSV file format
            }
    
            while(recordset.EOF === false) { //iterate through recordset
                if(data.download === true) { //if download flag is set build string containing CSV content
                    var row = [];
    
                    for(var i = 0, count = sqlHeaderRow.length; i < count; ++i) {
                        row.push(String(recordset.Fields(sqlHeaderRow[i]).Value).replace('"', '""'));
                    }
    
                    exportData.push('"' + row.join('","') + '"');
                }
    
                else { //else format data for display
                    var row = {};
    
                    for(var i = 1, fieldsCount = recordset.Fields.Count; i < fieldsCount; ++i) {
                        var field = recordset.Fields(i),
                            name = field.Name,
                            value = field.Value;
    
                        row[name] = value;
                    }
    
                    tableData.data.push(row);
                }
    
                recordset.MoveNext();
            }
    
    if(data.download === true) { //save CSV content in server-side storage
        Session('download-' + data.timestamp) = exportData.join('\r\n'); //this is where timestamp value is used (can be any other unique value)
    }
    
    Response.Write(JSON.stringify(tableData)); //return data for display, if download flag is set, tableData.data = []
    
    0 讨论(0)
提交回复
热议问题