关于asp.net:将多个html表格导出到Excel

Export multiple html tables to Excel

我已经在互联网上寻找答案,虽然我找到了一些答案,但它们大多不完整或不起作用。

我想做的是:我有一个信息页面,其中显示有关客户或服务器(或其他)的信息,此信息显示在一个表中,有时显示在多个表中(我有时创建自己的表一些数据并使用 Html.Grid(Model.list) 为存储在列表中的其余数据创建表,全部在 1 页上)。

我发现这个网站很棒:http://www.excelmashup.com/ 并且完全符合我对 1 个表的要求,尽管我需要多个表(它们必须都在同一个 Excel 文件中) .我知道我可以创建多个文件(每个表 1 个),但这不是所需的输出。

于是我继续搜索,在stackoverflow上找到了一个帖子:Export multiple HTML tables to Excel with JavaScript function

这看起来很有希望,所以我尝试使用它,但代码有一些我试图修复的小错误:

1
2
3
4
5
6
7
8
9
10
11
var tableToExcel = (function () {
    var uri = 'data:application/vnd.ms-excel;base64,'
        , template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}</table></body></html>'
        , base64 = function (s) { return window.btoa(unescape(encodeURIComponent(s))) }
        , format = function (s, c) { return s.replace(/{(\\w+)}/g, function (m, p) { return c[p]; }) }
    return function (table, name) {
        if (!table.nodeType) table = document.getElementById(table)
        var ctx = { worksheet: name || 'Worksheet', table: table.innerHTML }
        window.location.href = uri + base64(format(template, ctx))
    }
})()

我用来触发它的按钮:

1
<input type="button" onclick="tableToExcel('InformatieTable', 'W3C Example Table')" value="Export to Excel">

但是没有用(我不知道如何处理 if (!table.nodeType) table = table 行,所以我只是评论它,因为它似乎没有什么特别的)。

现在我收到一个错误,或者说不是真正的错误,但这就是我尝试运行此代码时所说的内容:

Resource interpreted as Document but transferred with MIME type application/vnd.ms-excel:"data:application/vnd.ms-excel;base64,PGh0bWwgeG1sbnM6bz0idXJuOnNjaGVtYXMtbW…JzZXQ9VVRGLTgiLz48L2hlYWQ+PGJvZHk+PHRhYmxlPjwvdGFibGU+PC9ib2R5PjwvaHRtbD4=".

我在我的浏览器中下载了一个 Excel 文件,但是当我尝试打开它时,我收到一个关于内容和文件扩展名不匹配以及我是否仍想打开它的错误。所以如果我点击确定,它会打开一个空的 Excel 工作表,就是这样。

我目前正在尝试修复该错误,但我认为这不会对 Excel 文件的内容产生任何影响。

有没有人可以帮我解决这个问题?或者提供其他方式来执行此操作?

我更喜欢它在客户端(如 jQuery/java)而不是服务器端运行以最小化服务器负载。

编辑

我在 http://www.codeproject.com/Tips/755203/Export-HTML-table-to-Excel-With-CSS 上找到了一个更好的 jQuery 示例(一个可以工作的)
这会将 1 个表格转换为 excel 文件,这显然不够好。但是现在我有代码来执行此操作,因此我应该能够对其进行调整以循环遍历网页上的所有表格。

还将此示例中的代码更新为我现在使用的正确版本。
我仍然遇到同样的错误,但是当我在尝试打开 Excel 文件时单击"确定"时,它确实向我显示了表格的内容,所以我现在只是忽略它。任何对此有解决方案的人请分享。


感谢@Axel Richter,我得到了答案,他让我回答了以下问题

我已经对代码进行了一些修改,因此它会占用网页上的所有表格,所以现在看起来像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<script type="text/javascript">
    var tablesToExcel = (function () {
        var uri = 'data:application/vnd.ms-excel;base64,'
        , tmplWorkbookXML = '<?xml version="1.0"?><?mso-application progid="Excel.Sheet"?><Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">'
          + '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"><Author>Axel Richter</Author><Created>{created}</Created></DocumentProperties>'
          + '<Styles>'
          + '<Style ss:ID="Currency"><NumberFormat ss:Format="Currency"></NumberFormat></Style>'
          + '<Style ss:ID="Date"><NumberFormat ss:Format="Medium Date"></NumberFormat></Style>'
          + '</Styles>'
          + '{worksheets}</Workbook>'
        , tmplWorksheetXML = '<Worksheet ss:Name="{nameWS}"><Table>{rows}</Table></Worksheet>'
        , tmplCellXML = '<Cell{attributeStyleID}{attributeFormula}><Data ss:Type="{nameType}">{data}</Data></Cell>'
        , base64 = function (s) { return window.btoa(unescape(encodeURIComponent(s))) }
        , format = function (s, c) { return s.replace(/{(\\w+)}/g, function (m, p) { return c[p]; }) }
        return function (wsnames, wbname, appname) {
            var ctx ="";
            var workbookXML ="";
            var worksheetsXML ="";
            var rowsXML ="";
            var tables = $('table');
            for (var i = 0; i < tables.length; i++) {
                for (var j = 0; j < tables[i].rows.length; j++) {
                    rowsXML += '<Row>'
                    for (var k = 0; k < tables[i].rows[j].cells.length; k++) {
                        var dataType = tables[i].rows[j].cells[k].getAttribute("data-type");
                        var dataStyle = tables[i].rows[j].cells[k].getAttribute("data-style");
                        var dataValue = tables[i].rows[j].cells[k].getAttribute("data-value");
                        dataValue = (dataValue) ? dataValue : tables[i].rows[j].cells[k].innerHTML;
                        var dataFormula = tables[i].rows[j].cells[k].getAttribute("data-formula");
                        dataFormula = (dataFormula) ? dataFormula : (appname == 'Calc' && dataType == 'DateTime') ? dataValue : null;
                        ctx = {
                            attributeStyleID: (dataStyle == 'Currency' || dataStyle == 'Date') ? ' ss:StyleID="' + dataStyle + '"' : ''
                               , nameType: (dataType == 'Number' || dataType == 'DateTime' || dataType == 'Boolean' || dataType == 'Error') ? dataType : 'String'
                               , data: (dataFormula) ? '' : dataValue.replace('', '')
                               , attributeFormula: (dataFormula) ? ' ss:Formula="' + dataFormula + '"' : ''
                        };
                        rowsXML += format(tmplCellXML, ctx);
                    }
                    rowsXML += '</Row>'
                }
                ctx = { rows: rowsXML, nameWS: wsnames[i] || 'Sheet' + i };
                worksheetsXML += format(tmplWorksheetXML, ctx);
                rowsXML ="";
            }

            ctx = { created: (new Date()).getTime(), worksheets: worksheetsXML };
            workbookXML = format(tmplWorkbookXML, ctx);

            console.log(workbookXML);

            var link = document.createElement("A");
            link.href = uri + base64(workbookXML);
            link.download = wbname || 'Workbook.xls';
            link.target = '_blank';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
    })();

所以现在当我想要一个页面有一个导出到 excel 的选项时,我会添加对该脚本的引用,并将以下按钮添加到我的页面:

1
<button onclick="tablesToExcel(['ServerInformatie', 'Relaties'], 'VirtueleMachineInfo.xls', 'Excel')">Export to Excel</button>

所以方法:

1
tablesToExcel(WorksheetNames, fileName, 'Excel')

其中 worksheetNames 是一个数组,它需要包含与页面上的表格一样多(或更多)的名称。您当然可以选择以不同的方式创建工作表名称。
其中 fileName 当然是您将要下载的文件的名称。

在一张工作表中没有全部内容是一种耻辱,但至少现在可以这样做。


这是我用来将多个 HTML 表格放在同一个 Excel 工作表中的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import TableExport from 'tableexport';

const tbOptions = {
  formats: ["xlsx"],    // (String[]), filetype(s) for the export, (default: ['xlsx', 'csv', 'txt'])
  bootstrap: true,                   // (Boolean), style buttons using bootstrap, (default: true)
  exportButtons: false,                // (Boolean), automatically generate the built-in export buttons for each of the specified formats (default: true)
  position:"bottom",                 // (top, bottom), position of the caption element relative to table, (default: 'bottom')
}

DowlandExcel = (key) => {
  const table = TableExport(document.getElementById(key), tbOptions);
  var exportData = table.getExportData();
  var xlsxData = exportData[key].xlsx;
  console.log(xlsxData); // Replace with the kind of file you want from the exportData
  table.export2file(xlsxData.data, xlsxData.mimeType, xlsxData.filename, xlsxData.fileExtension, xlsxData.merges, xlsxData.RTL, xlsxData.sheetname)
}

DowlandExcelMultiTable = (keys) => {

  const tables = []
  const xlsxDatas = []
  keys.forEach(key => {
    const selector = document.getElementById(key);
    if (selector) {
      const table = TableExport(selector, tbOptions);
      tables.push(table);
      xlsxDatas.push(table.getExportData()[key].xlsx)
    }
  });

  const mergeXlsxData = {
    RTL: false,
    data: [],
    fileExtension:".xlsx",
    filename: 'rapor',
    merges: [],
    mimeType:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    sheetname:"Rapor"
  }
  for (let i = 0; i < xlsxDatas.length; i++) {
    const xlsxData = xlsxDatas[i];
    mergeXlsxData.data.push(...xlsxData.data)

    xlsxData.merges = xlsxData.merges.map(merge => {
      const diff = mergeXlsxData.data.length - xlsxData.data.length;

      merge.e.r += diff;
      merge.s.r += diff;

      return merge
    });
    mergeXlsxData.merges.push(...xlsxData.merges)
    mergeXlsxData.data.push([null]);
  }
  console.log(mergeXlsxData);
  tables[0].export2file(mergeXlsxData.data, mergeXlsxData.mimeType, mergeXlsxData.filename, mergeXlsxData.fileExtension, mergeXlsxData.merges, mergeXlsxData.RTL, mergeXlsxData.sheetname)
}