Html表转换为excel并通过电子邮件发送

时间:2016-11-29 08:29:14

标签: c# excel email asp.net-mvc-5

我正在开发一个可以使用html表生成excel文件的应用程序。到目前为止,我开发了html表下载作为excel文件部分。 (这发生在客户端使用javascript)。现在我需要将带有附件的电子邮件(excel文件)发送到特定人的电子邮件地址。所以我很困惑如何做到这一点,因为到目前为止我在客户端生成excel并需要通过电子邮件发送该文件。在这种情况下是否需要将客户端excel复制到服务器?如果是这样怎么办? 请给我指点。

  

更新1(添加代码)

这是javascript,我曾经将html表作为excel下载到客户端。

    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 (tables, wsnames, wbname, appname) {
            var ctx = "";
            var workbookXML = "";
            var worksheetsXML = "";
            var rowsXML = "";

            for (var i = 0; i < tables.length; i++) {
                if (!tables[i].nodeType) tables[i] = document.getElementById(tables[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
                               , 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);

            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保存到服务器并将其作为电子邮件发送。

2 个答案:

答案 0 :(得分:0)

您无法使用HTML表格创建Excel文件。这是一个用于伪造实际Excel文件的黑客。 Excel不会被欺骗,它会识别HTML文件并尝试使用默认值导入数据。这很容易因各种原因而中断,例如小数和日期的不同区域设置。

Excel文件只是压缩的XML文件。您可以使用XML操作,Open XML SDK或EPPlus等库创建它们。

使用EPPlus创建Excel文件就像调用LoadFromCollectionLoadFromDatatable方法一样简单。工作表可以保存到任何流,包括FileStream或MemoryStream。 MemoryStream可用于将数据作为shown in this answer发送到Web浏览器:

public ActionResult ExportData()
{

    //Somehow, load data to a DataTable

    using (ExcelPackage package = new ExcelPackage())
    {
        var ws = package.Workbook.Worksheets.Add("My Sheet");
        //true generates headers
        ws.Cells["A1"].LoadFromDataTable(dataTable, true);

        var stream = new MemoryStream();
        package.SaveAs(stream);

        string fileName = "myfilename.xlsx";
        string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

        stream.Position = 0;
        return File(stream, contentType, fileName);
    }
}

也可以从MemoryStream创建邮件附件。 Attachment(Stream, string,string)构造函数接受任何流作为输入。可以修改上面的示例以创建附件,而不是将数据发送到浏览器:

public void SendData(string server, string recipientList)
{

    //Same as before
    using (ExcelPackage package = new ExcelPackage())
    {
        var ws = package.Workbook.Worksheets.Add("My Sheet");
        ws.Cells["A1"].LoadFromDataTable(dataTable, true);
        var stream = new MemoryStream();
        package.SaveAs(stream);

        string fileName = "myfilename.xlsx";
        string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

        stream.Position = 0;
        SendExcel(server,recipientList);
    }
}

void SendExcel(string server, string recipientList)
{
        //Send the file
        var message = new MailMessage("logMailer@contoso.com", recipientList);
        message.Subject = "Some Data";
        Attachment data = new Attachment(stream, name, contentType);
        // Add the attachment to the message.
        message.Attachments.Add(data);
        // Send the message.
        // Include credentials if the server requires them.
        var client = new SmtpClient(server);
        client.Credentials = CredentialCache.DefaultNetworkCredentials;
        client.Send(message);
    }
}

<强>更新

如果使用像js-xlsx这样的库,在客户端生成XSLX表会变得容易多了。甚至还有generates an XLSX file from an HTML table

的样本

答案 1 :(得分:0)

根据我们的讨论: 1.您需要从客户端向服务器发送数据 您可以使用此代码执行此操作,使用ajax将标头和值发送到服务器,您也可以根据需要过滤列

function SaveToServer() {
        var gov = GetHeaders('tbl');

        $.ajax({
            url: '@Url.Content("~/Home/ReciveData")',
            data: { headers: JSON.stringify(gov.heasers), data: JSON.stringify(gov.data) },
            success: function (data) {
         // Success
            },
            error: function (xhr) {
            }
        });

    }

    function GetHeaders(tableName) {

        table = document.getElementById(tableName);
        var tbl_Hdata = [];
        var tbl_Data = [];
        for (var i = 0, row; row = table.rows[i]; i++) {
            var rowData = [];
            for (var j = 0, col; col = row.cells[j]; j++) {
                // add column filter
                if (i == 0) {
                    tbl_Hdata.push(col.innerHTML);
                }
                else {
                    rowData.push(col.innerHTML);
                }
            }
            if (i > 0) {
                tbl_Data.push(rowData);
            }
        }

        return { heasers: tbl_Hdata, data: tbl_Data };
    }
  1. 现在我们想要重新接收这些数据并将其转换为datatable以将其保存到服务器端的Excel中 使用NPOI

    public void ReciveData(string headers, string data)
    {
        #region Read Data
        List<string> tbl_Headers = new List<string>();
        List<List<string>> tbl_Data = new List<List<string>>();
        tbl_Headers = Newtonsoft.Json.JsonConvert.DeserializeObject<List<string>>(headers);
        tbl_Data = Newtonsoft.Json.JsonConvert.DeserializeObject<List<List<string>>>(data);
        #endregion
    
        #region Create Data Table
        DataTable dataTable = new DataTable("Data");
        foreach (var prop in tbl_Headers)
        {
            dataTable.Columns.Add(prop);
        }
        DataRow row;
        foreach (var rw in tbl_Data)
        {
            row = dataTable.NewRow();
    
            for (int i = 0; i < rw.Count; i++)
            {
                row[tbl_Headers[i]] = rw[i];
            }
            dataTable.Rows.Add(row);
        }
        #endregion
    
        #region Save To excel
        string path = @"D:\";
        string fileName = "";
        GenerateExcelSheetWithoutDownload(dataTable, path, out fileName); 
        #endregion
    
    }
    
    public bool GenerateExcelSheetWithoutDownload(DataTable dataTable, string exportingSheetPath, out string exportingFileName)
    {
        #region Validate the parameters and Generate the excel sheet
        bool returnValue = false;
        exportingFileName = Guid.NewGuid().ToString() + ".xls";
    
        if (dataTable != null && dataTable.Rows.Count > new int())
        {
            string excelSheetPath = string.Empty;
            #region Check If The directory is exist
            if (!Directory.Exists(exportingSheetPath))
            {
                Directory.CreateDirectory(exportingSheetPath);
            }
    
            excelSheetPath = exportingSheetPath + exportingFileName;
            FileInfo fileInfo = new FileInfo(excelSheetPath);
            #endregion
    
            #region Write stream to the file
            MemoryStream ms = DataToExcel(dataTable);
            byte[] blob = ms.ToArray();
            if (blob != null)
            {
                using (MemoryStream inStream = new MemoryStream(blob))
                {
                    FileStream fs = new FileStream(excelSheetPath, FileMode.Create);
                    inStream.WriteTo(fs);
                    fs.Close();
                }
            }
            ms.Close();
            returnValue = true;
            #endregion
        }
    
        return returnValue;
        #endregion
    }
    
    private static MemoryStream DataToExcel(DataTable dt)
    {
        MemoryStream ms = new MemoryStream();
        using (dt)
        {
    
            #region Create File
            HSSFWorkbook workbook = new HSSFWorkbook();//Create an excel Workbook
            ISheet sheet = workbook.CreateSheet("data");//Create a work table in the table
    
            int RowHeaderIndex = new int();
            #endregion
    
            #region Table Headers
            IRow headerTableRow = sheet.CreateRow(RowHeaderIndex);
            if (dt != null)
            {
                foreach (DataColumn column in dt.Columns)
                {
                    headerTableRow.CreateCell(column.Ordinal).SetCellValue(column.Caption);
                }
                RowHeaderIndex++;
            }
            #endregion
    
            #region Data
    
            foreach (DataRow row in dt.Rows)
            {
                IRow dataRow = sheet.CreateRow(RowHeaderIndex);
                foreach (DataColumn column in dt.Columns)
                {
                    dataRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString());
                }
                RowHeaderIndex++;
            }
            #endregion
    
            workbook.Write(ms);
            ms.Flush();
            //ms.Position = 0;
        }
        return ms;
    }
    
  2. 现在您可以将此文件作为附件发送到邮件