如何通过拆分为多个Excel文件导出Jquery DataTable?

问题描述

当前,我有29000条记录的服务器端处理数据表,当我尝试将其导出到excel时,html.datatables.net将长度限制为5K。我必须通过将它们拆分成多个文件来导出其余记录(24K)。

下面是我的代码示例,该代码导出所有数据,我可以在哪里重复访问并多次下载excel?

$('#yTable').DataTable({
      serverSide: true,dom: 'Bfrtip',ajax: //my ajax call...,buttons : [{
                    extend: 'excel',text: 'Export to Excel',action: newExportAction,customize: function(xlsx) {...}
                }],columns: columnsToShow,columnDefs: colDefs,deferRender: true
      });

var oldExportAction = function(self,e,dt,button,config) {
      if (button[0].className.indexOf('buttons-excel') >= 0) {
            if ($.fn.dataTable.ext.buttons.excelHtml5.available(dt,config)) {
              $.fn.dataTable.ext.buttons.excelHtml5.action.call(self,config);
            } else {
              $.fn.dataTable.ext.buttons.excelFlash.action.call(self,config);
            }
          } else if (button[0].className.indexOf('buttons-print') >= 0) {
            $.fn.dataTable.ext.buttons.print.action(e,config);
          }
        };
var newExportAction = function(e,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...
    var splitByNoOfRecords = 5000;
    var totalNoOfRecords = 29000;
    var totalNoFilesToDownload = Math.ceil(totalNoOfRecords / splitByNoOfRecords);
    if (totalNoFilesToDownload == 0) {
      data.start = 0;
      data.length = 2147483647;
      dt.one('preDraw',settings) {
        // Call the original action function
        oldExportAction(self,config);
        htmlListingOldStart = oldStart;
        dt.one('preXhr',data) {
          // DataTables thinks the first item displayed getFullDataHtmlListingFlag
          // 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;
      });
    } else {
      for (var i = 0; i < totalNoFilesToDownload; i++) {
        data.start = i * splitByNoOfRecords;
        data.length = i + splitByNoOfRecords;
        dt.one('preDraw',settings) {
          // Call the original action function
          oldExportAction(self,config);
          htmlListingOldStart = oldStart;
          dt.one('preXhr',data) {
            // DataTables thinks the first item displayed getFullDataHtmlListingFlag
            // 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();
};


解决方法

我试图使用此newExportAction函数,但是dt.one('preXhr',function(e,s,data)上的数据以字符串而不是对象的形式出现。

因此不可能像使用此数据一样进行变量赋值。length = 2147483647;

在过去的24小时里,我一直处于这种状态,并在阅读全文,以找到使用preXhr +变量分配的方法。

我还执行了一个没有运气的parsem字符串化

                dt.one('preXhr',function (e,s,data) {
                    // Just this once,load all data from the server...

                    var dataObj = JSON.parse(data);
                    dataObj.start = 0;
                    dataObj.length = -1;            
                    
                    data = JSON.stringify(dataObj);

我正在使用最新版本的Jquery和数据表

有什么主意吗?

,

感谢您的想法@Akarsh。是的,这正是我所做的。

使用上面公开的代码的相同结构,我将length = -1保存在全局变量中,并在ajax调用中使用它。

但是我遇到另一个问题。该操作在结构中链接了多个级别的predraw + preXhr,因此,在excel生成阶段之前,我们需要使用lenght = -1来获取所有记录,导出excel和恢复到原始页面长度和页面位置。

例如,在我的情况下,这是我检查是否要导出excel的ajax。该布尔值来自下面也将描述的操作。

dtDenuncias.DataTable({
    ajax: {
        url: contexto + "API/funcyURL",type: 'POST',// async: false,contentType: "application/json",data: function (data,settings) {       
            
            if (viewModel.Excel == 'true'){
                data.start = viewModel.start;
                data.length = viewModel.length;
                // settings._iDisplayStart = viewModel.start;
                // settings._iDisplayLength = viewModel.length;
            }   

            return JSON.stringify(data);
        },},

在这里,您可以编辑newExport和oldExport函数

            var oldExportAction = function (self,e,dt,button,config) {

                // console.log('oldExportAction - Exporta Excel');
                $.fn.dataTable.ext.buttons.excelHtml5.action.call(self,config);
            };
            
            var newExportAction = function (e,config) {

                viewModel.Excel = 'true';

                viewModel.oldStart = dt.settings()[0]._iDisplayStart;
                viewModel.oldLenght = dt.settings()[0]._iDisplayLength;
                viewModel.start = 0;
                viewModel.length = -1;              
                
                var self = this;

                dt.one('preXhr',data) {

                    // Just this once,load all data from the server...

                    dt.one('preDraw',settings) {

                       // Call the original action function 
                        oldExportAction(self,config);

                        dt.one('preXhr',function (event,settings,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 = viewModel.oldStart;                           
                            viewModel.start = viewModel.oldStart;
                        });
            
                        viewModel.Excel = 'false';

                        // 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();               
            };  

看起来一切都差不多了,excel可以完美地导出所有记录,并且页面长度也恢复为原始值,但是,我不知道如何将视图返回到我们原来的页面导出Excel之前。看来return = false不能防止抽奖再次发生。

preXhr将数据实现为包含json对象但以字符串格式而不是真实对象的字符串类型来实现是很可惜的。 此外,如果您解析为json,添加长度并通过序列化返回到字符串,则该值也会丢失,因此在ajax调用之前没有实际使用此preXhr函数修改值。

我想知道为什么他们会在最新版本中更改此行为,例如该preXhr在过去工作的示例,但现在无法像这样编写代码。

在接下来的几周内,我将尽早尝试在后端编写excel导出代码,我们需要直接从后端处理这种大型导出。这将在C#MVC中完成,如果可以运行,我将返回带有示例代码的论坛。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...