首页 > 解决方案 > 基于单元格类的 DataTables Excel 样式

问题描述

我正在使用DataTables 插件导出月历视图;我需要根据DataTables日历视图中对应单元格的类在 Excel 文件中设置单元格样式。
我知道如何设置导出的 excel 文件的样式,customize: function( xlsx, index ) {}但是在我在论坛上看到的示例中,我找不到一种基于 DataTables 中 corrispondig 单元格的类来设置 excel 单元格样式的方法看法。
我创建了自己的 xml 样式,如下所示:

customize: function( xlsx, index ) {
  var new_style = '<?xml version="1.0" encoding="UTF-8"?>'+
  '<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" '+
  'xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" '+
  'xmlns:x14ac="https://schemas.microsoft.com/office/spreadsheetml/2009/9/ac" mc:Ignorable="x14ac">'+
    '<numFmts count="2">'+
      '<numFmt numFmtId="164" formatCode="0.0" />'+
      '<numFmt numFmtId="165" formatCode="\d\d\d" />'+
    '</numFmts>'+
    '<fonts count="4" x14ac:knownFonts="1">'+

    ...... a lot of stuff here ....

    '<extLst>'+
      '<ext xmlns:x14="https://schemas.microsoft.com/office/spreadsheetml/2009/9/main" uri="{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}">'+
        '<x14:slicerStyles defaultSlicerStyle="SlicerStyleLight1" />'+
      '</ext>'+
    '</extLst>'+
  '</styleSheet>';

如果将扩展名更改为然后解压缩,则styles.xml可以在文件中找到此文件 。要将样式应用于我正在执行的 excel 单元格:.xlsx.zip

  xlsx.xl['styles.xml'] = $.parseXML(new_style);
  var sheet = xlsx.xl.worksheets['sheet1.xml'];

  $('row:first c', sheet).attr( 's', '1' );
  $('row:eq(1) c', sheet).attr( 's', '2' );
  $('row:eq(2) c', sheet).attr( 's', '3' );
}

我需要做的是:

     $('row:eq(3) c', sheet).hasClass('custom').attr( 's', '1' ); //not working

或者:

    $('row c[r^="B"]', sheet).each( function () {
       if ( $(this).hasClass('custom') ) {
       $(this).attr( 's', '4' );
      }
    }); // not working

基本上我正在处理一排单元格(超过 30 个,所以我有 AA、AB、AC 等),我需要一种方法来区分其中一些以添加不同的样式,如您所见标题有31 个带有日历日/名称的单元格,我希望周六和周日的列具有灰色背景,就像它们在数据表中一样。

这是数据表:

数据表

这是到目前为止的 excel 文件,我需要将SabDom列设为灰色

文件

更新 * 使用@andrewjames解决方案和@georg解决方案,用于在此处发布的双字母将数字转换为 26 个字符以外的字母

function colName(n) {
  var ordA = 'A'.charCodeAt(0);
  var ordZ = 'Z'.charCodeAt(0);
  var len = ordZ - ordA + 1;
  var s = "";
  while(n >= 0) {
    s = String.fromCharCode(n % len + ordA) + s;
    n = Math.floor(n / len) - 1;
  }
  return s;
}

var cellIndexes = tabellaOre.cells(".Sab, .Dom").indexes();

for (var i = 0; i < cellIndexes.length; i++) {
  var cellIndex = cellIndexes[i];
  var tblRow = cellIndex['row']+4; //changed to my needs
  var tblCol = cellIndex['column']; //removed +1
  // var xlCol = String.fromCharCode(64 + tblCol); changed with follow
  var xlCol = colName(tblCol);

  // .... previous stuff here, it was already in a for() loop, so still working

  $('row c[r='+xlCol+tblRow+']', sheet).attr('s','12');
}

这是结果:

文件

正如@andrewjames 在他的回答中正确所说:

我的幼稚实现将失败超过 26 列:

colName(n)功能解决了这个问题。
最后一步是用自己的样式设置粗边框的单元格,但我可以认为这已经解决了。

标签: excelxmlfiledatatablesexport

解决方案


假设:

听起来您已经styles.xml按照您想要的方式自定义了嵌入式,因此您可以从其<cellXfs>部分中知道要引用的样式索引值。

听起来好像缺少的部分是知道哪些 DataTables 单元格已被赋予了哪些 CSS 样式类,因此您可以<cellXfs>为等效的 Excel 单元格选择相关索引。

建议的方法:

这利用了customize函数可以传递 3 个变量的事实:

  • Excel 的 XML 文件
  • 表示按钮对象的对象
  • 数据表实例

我们使用最后一个将 HTML 中的类映射到 Excel 中的单元格:

  var table = $('#example').dataTable({
    dom: 'Bfrtip',
    buttons: [
      {
        extend: 'excelHtml5',
        title: '', // no title row
        text: 'Excel',
        customize: function ( xlsx, btnObj, tableInst ){

          var cellIndexes = tableInst.cells(".mycustom").indexes();
          for (var i = 0; i < cellIndexes.length; i++) {
            var cellIndex = cellIndexes[i];
            var tblRow = cellIndex['row']+1; // adjusted from 0 indexed
            var tblCol = cellIndex['column']+1; // adjusted from 0 indexed
            var xlCol = String.fromCharCode(64 + tblCol); // DANGER: fails after Z (26 columns)
            alert('table row ' + tblRow + ' col ' + tblCol
                + ' maps to excel cell ref ' + xlCol + tblRow);
          }
        }
      }
    ]

  });

这不应用任何样式,它只是向您展示如何确定哪些 DataTable 单元格已被赋予特定样式,并将这些单元格索引转换为 Excel 样式的单元格引用。

因此,对于以下示例数据...

<table id="example" class="display nowrap dataTable cell-border" style="width:100%">
        <thead>
            <tr>
                <th>Head 1</th>
                <th>Head 2</th>
                <th>Head 3</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Row 1 column 1</td>
                <td>Row 1 column 2</td>
                <td>Row 1 column three</td>
            </tr>
            <tr>
                <td>Row 2 column 1</td>
                <td>Row 2 column 2</td>
                <td>Row 2 column 3</td>
            </tr>
            <tr>
                <td>Row 3 column 1</td>
                <td class="mycustom">Row 3 column 2</td>
                <td>Row 3 column 3</td>
            </tr>
            <tr>
                <td>Row 4 column 1</td>
                <td>Row 4 column 2</td>
                <td>Row 4 column 3</td>
            </tr>
            <tr>
                <td class="mycustom">Row 5 column 1</td>
                <td>Row 5 column 2</td>
                <td>Row 5 column 3</td>
            </tr>
        </tbody>
    </table>

...上面的代码生成 2 个警报,如下所示:

table row 3 col 2 maps to excel cell ref B3
table row 5 col 1 maps to excel cell ref A5

然后,您可以在需要的选择器中使用B3andA5值 - 例如:

$('c[r=B3] t', sheet).attr( 's', '25' );

附加说明

此处描述了DataTablescells().indexes()函数。

我的幼稚实现将失败超过 26 列:

var xlCol = String.fromCharCode(64 + tblCol);

但是,如果需要,对 Excel 列“AA”、“AB”等进行扩展应该不会太难。

如果您想在列(或行)级别而不是单元格级别工作,我没有尝试过 - 但它应该是上面的一个稍微简单的版本。


推荐阅读