Как позволить Excel уважать новые строки в ячейках, которые содержат строки с символами новой строки - PullRequest
0 голосов
/ 20 июня 2019

Наше веб-приложение имеет возможность экспортировать HTML-таблицы в Excel, и это прекрасно работает. Но мы не можем заставить его поддерживать несколько строк в столбцах. Мы испробовали множество решений, в основном с CSS, как описано здесь но ничего из того, что мы обнаружили, не помогло. Наш поток в основном так:
Мы создаем хэш-таблицу, в которой ключи являются заголовками столбцов, а значения - значениями ячеек. Затем мы создаем HTML-таблицу из хеш-таблицы с помощью Razor, и, наконец, эта HTML-таблица попадает к клиенту, где она преобразуется в шаблон XML, который Excel понимает, и загружается браузером. Вот некоторый код, чтобы попытаться дать вам почувствовать, какой код задействован:
Код бритвы (состоит из страницы и компонента):
Страница:

@using System.Text
@using System.Text.Encodings.Web
@using Mchp.DigitalRural.Services.ViewModel
@model DataToExportViewModel
@{
    Layout = null;
}
@{
    var htmlBulk = string.Empty;
    htmlBulk += $"<table><tr><td><div style='text-align:center;font-size:2em;margin:3em 0 5em;width:35%;'>{Model.DocumentTitle}</div></td></tr>";
    htmlBulk += $"<tr><td><div style='text-align:center;font-size:1.5em;white-space:pre;'>{Model.BySearchTerms}</div><br/></td></tr></table>";
    var sb = new StringBuilder();
    using (var writer = new System.IO.StringWriter(sb))
    {
        (await Component.InvokeAsync("PlacesTable", Model.FieldsToExport)).WriteTo(writer, HtmlEncoder.Default);
        htmlBulk += sb.ToString();
    }
    @Html.Raw(htmlBulk) <-- Should this line be replaced with something else? I mean, if we replace the newlines ("\r\n") with "<br/>" the string "<br/>" is gets concatenated.
}

и компонент бритвы, который содержит шаблон для HTML-таблицы:

@model IEnumerable<Dictionary<string, string>>
<table>
    <thead>
    <tr>
        @if (Model.Any()) {
            foreach (var edPlace in Model.First())
            {
                <th>@edPlace.Key</th>
            }
        }
    </tr>
    </thead>
    <tbody style="text-align: center; font-size: 12px;">
    @foreach (var edPlace in Model)
    {
        <tr>
            @foreach (var kvPair in edPlace)
            {
                <td>@kvPair.Value</td> <-- this is where newlines might exist, within the 'Value' property, and that are not displayed in the excel downloaded
            }            
        </tr>
    }
    </tbody>
</table>

и, наконец, фабрика angularjs преобразует HTML-таблицу в Excel.

    angular
    .module('common')
    .factory('Excel', function ($window) {
        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"><meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8">' +
                    '<head><!--[if gte mso 9]><xml>' +
                    '<x:ExcelWorkbook>' +
                        '<x:ExcelWorksheets>' +
                            '<x:ExcelWorksheet>' +
                                '<x:Name>{worksheet}</x:Name>' +
                                '<x:WorksheetOptions>' +
                                        '<x:DisplayGridlines/>' +
                                        '<x:DisplayRightToLeft/>' + //Important - Set direction of sheet from Right To Left
                                '</x:WorksheetOptions>' +
                            '</x:ExcelWorksheet>' +
                        '</x:ExcelWorksheets>' +
                    '</x:ExcelWorkbook>' +
                    '</xml><![endif]--></head><body><table style="font-size:24px;">{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]; }) },
            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><Font ss:Size="11"></Font></Style>' +
                '<Style ss:ID="CurrencyBold"><NumberFormat ss:Format="Currency"></NumberFormat><Font ss:Size="11" ss:Bold="1"></Font></Style>' +
                '<Style ss:ID="Date"><NumberFormat ss:Format="Medium Date"></NumberFormat><Font ss:Size="11"></Font></Style>' +
                '<Style ss:ID="BoldText"><Font ss:Bold="1" ss:Size="11"></Font></Style>' +
                '<Style ss:ID="Title"><Font ss:Bold="1" ss:Size="12"></Font></Style>' +
            '</Styles>' + '{worksheets}</Workbook>',
            tmplWorksheetXml = '<Worksheet ss:Name="{nameWS}"><Table><Column ss:Index="2" ss:Width="110"/> {rows}</Table></Worksheet>',
            tmplCellXml = '<Cell{attributeStyleID}{attributeFormula}><Data ss:Type="{nameType}">{data}</Data></Cell>';

        return {
            tableHtmlToExcel: function (tableHtml, worksheetName) {
                var ctx = { worksheet: worksheetName, table: tableHtml },
                    href = uri + base64(format(template, ctx));
                return href;
            },
            some other not related functions...
        };
    })
    .service("exportSrv", ExportSrv);  

Так, как мы можем сказать Excel, чтобы отображать новые строки в Excel?

спасибо,
ashilon

...