从 DataTables.js 导出所有行,同时只显示其中的一些并保持分页

Export ALL rows from DataTables.js while displaying only some of them and keeping the pagination

在 DataTable 上,我需要:

为了在屏幕上只显示所需的行,我使用 drawCallback

// Each row has an ItemId property. Several rows may have the same ItemId
// I want to display only the first row for each ItemId, but export all rows
drawCallback: function (settings) {
    var api = this.api();
    var ids = [];
                
    $.each(api.rows({ page: 'current' }).data(), function (i, v) {
        if ($.inArray(v.ItemId, ids) != -1)
            $("#myDatatable tbody tr:eq(" + i + ")").css("visibility", "collapse")
        else
            ids.push(v.ItemId);
    })
},

但是,我正在使用分页系统,我想每页显示 30 可见 行。

如何在屏幕上保留 30 可见 行,同时导出所有行(可见+隐藏)?

郑重声明,我使用的是 DataTables 1.10.21

问题

我认为按照问题中显示的方式从 HTML table 中删除行总是会导致您描述的问题:一页上的行太少。

这是因为您已从 HTML table(DOM)中删除了数据,但删除了 DataTables(存储所有数据的 JavaScript 对象)对这些变化一无所知。因此,它认为您有整页数据,显示 30 条记录。

一个解决方案

您可以通过使用 DataTables 过滤机制来避免这个问题 - 但它有点笨拙,因为(如您在问题中所示)如何过滤行取决于前几行中的数据。

这是一种方法:

  1. 在 table 中创建一个隐藏列,并用指示是否应显示某行的特定文本值填充该列。

  2. 当导出到 Excel 时,您可以确保所有行(可见和隐藏)都被导出 - 并且您可以确保我们的额外隐藏列(来自上面的 (1))是未导出。

  3. 在“文档就绪”函数的末尾添加逻辑以计算哪些行是shown/hidden。这个逻辑基本上等同于你的问题。

代码:

$(document).ready(function() {

var firstFound = "##first_occurrence##"; // needs to be unique - must not clash with other data in the table

var table = $('#myDatatable').DataTable( {
  data: dataSet.data, // my test data is sourced from a JavaScript variable (see below)
  pageLength: 5, // just for testing
  columns: [
    { title: "Name", data: "name" },
    { title: "Office", data: "office" },
    { title: "Position", data: "position" }, // this is my equivalent of your ItemId column
    { title: "Start date", data: "start_date" },
    { title: "Salary", data: "salary" },
    { data: "id", visible: false } // this is where the 'firstFound' value is placed
  ],
  search: {
    search: firstFound // forces filtering to be applied
  },
  dom: 'Brtip',
  buttons: [
    { 
      title: '',
      extend: 'excel', 
      text: 'To Excel',
      exportOptions: {
        rows: { order:'current', search: 'none' }, // export all rows
        columns: [ 0, 1, 2, 3, 4 ] // export all columns apart from the final column in my table
      }
    }
  ]
} );

// the logic to populate the hidden column in my table:

var positions = [];

// column index 5 is the hidden column, used for filtering.
// column index 2 is my "job position" data (accountant, etc).
table.rows().every( function (rowIdx, tableLoop, rowLoop) {
  var filterCell = table.cell( { row: rowIdx, column: 5 } );
  var position = table.cell( { row: rowIdx, column: 2 } ).data();
  if ($.inArray(position, positions) === -1) {
    filterCell.data(firstFound);
    positions.push(position);
  } else {
    filterCell.data("");
  }
} );

// finally, re-draw the table to ensure the data changes are applied:
table.draw();

} );

这向您展示了一种方法。它可能不是您所需要的。例如,我特意隐藏了全局过滤框。一旦数据被过滤和显示,您就不能以其他方式重新过滤它。


作为参考,我的示例测试数据如下所示:

var dataSet = {
  "data": [
    {
      "id": "1",
      "name": "Tiger Nixon",
      "position": "System Architect",
      "salary": "0,800",
      "start_date": "2011/04/25",
      "office": "Edinburgh",
      "extn": "5421"
    },
    ... // and so on...
    {
      "id": "2",
      "name": "Garrett Winters",
      "position": "Accountant",
      "salary": "0,750",
      "start_date": "2011/07/25",
      "office": "Tokyo",
      "extn": "8422"
    }
  ]
};