Как экспортировать данные из C# из List <object>или IEnumerable в Excel (MS Open Xml)? - PullRequest
0 голосов
/ 07 мая 2020

Я пытаюсь экспортировать List<dynamic> или IEnumerable в файл Excel с помощью библиотеки Open XML Microsoft.

Библиотека: https://github.com/OfficeDev/Open-XML-SDK

Пример аналогичного запроса: https://www.codeproject.com/Articles/692121/Csharp-Export-data-to-Excel-using-OpenXML-librarie

Пример выше работает довольно хорошо, но между ними много кода (пока работает аккуратно, но я ищу оптимизацию)

Но документация этой библиотеки не расширяется (или содержит не так много примеров), и примеры, которые я видел, о том, как экспортировать данные в Excel, используют DataTable или Dataset; таким образом, они проводят разговор с List на DataTable для экспорта DataTable. И это кажется довольно сложным путем к тому, что другие библиотеки решают легче.

Итак, если у кого-то есть своего рода пример того, как сделать экспорт быстро и c, он будет оценен.

1 Ответ

0 голосов
/ 07 мая 2020

FYI, вот моя реализация с использованием кода @mikesknowledgebase (http://www.mikesknowledgebase.com - Веб-страница не работает ... но, по крайней мере, отдать должное: D)

Пост со всей информацией здесь


Итак, я его использовал для. Net Core 2.2; и намерение состоит в том, чтобы использовать этот метод для экспорта List<dynamic> в Excel.

Конечный результат (в простейшем примере):

[HttpGet("[action]")]
public FileResult exportExample()
{
    List<dynamic> data = new List<dynamic>();

    data.Add(new { a = 1, b = "HELLO WORLD", c = DateTime.Now });
    data.Add(new { a = 2, b = "TEST", c = 34 });

    // Implementation of Dictionary to limit the columns and the type of the List
    // Works with some standard, and flat files (Not with Dynamic Objects that have multiples levels - Indentation of a dynamic into a property)
    Dictionary<string, Type> columns = new Dictionary<string, Type>();
    columns.Add("a", typeof(int));
    columns.Add("b", typeof(string));
    columns.Add("c", typeof(object)); // Accepts any (Numbers or DateTime)

    string excelContentType;
    var excelStream = CreateExcelFile.CreateExcelStream(data, columns, out excelContentType);

    return File(excelStream, excelContentType, "report.xlsx");
}

Я создал несколько других методов внутри класс Майка ...

Метод для получения List с Dictionary<string, type> для столбцов ... и еще один параметр для возврата ContentType:

public static byte[] CreateExcelStream<T>(List<T> list, Dictionary<string, Type> columns, out string contentType )
{
    DataSet ds = new DataSet();

    ds.Tables.Add(ListToDataTable(list, columns));
    contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; // "application/vnd.ms-excel";

    return CreateExcelStream(ds).fwToByteArray();
}

Другой метод преобразования List в DataTable:

public static DataTable ListToDataTable<dynamic>(List<dynamic> list, Dictionary<string, Type> columns)
{
    DataTable dt = new DataTable();

    foreach (var column in columns)
        dt.Columns.Add(new DataColumn(column.Key, GetNullableType(column.Value)));

    foreach (var t in list)
    {
        DataRow row = dt.NewRow();

        ((object)t)
        .GetType()
        .GetProperties()
        .ToList()
        .ForEach(p =>
        {
            if (!IsNullableType(p.PropertyType))
                row[p.Name] = p.GetValue(t, null);
            else
                row[p.Name] = (p.GetValue(t, null) ?? DBNull.Value);
        });
        dt.Rows.Add(row);
    }
    return dt;
}

Я включил расширение для преобразования stream в byteArray:

public static byte[] fwToByteArray(this Stream stream)
{
    stream.Position = 0;
    byte[] buffer = new byte[stream.Length];

    for (int totalBytesCopied = 0; totalBytesCopied < stream.Length;)
        totalBytesCopied += stream.Read(buffer, totalBytesCopied, Convert.ToInt32(stream.Length) - totalBytesCopied);

    return buffer;
}

Остальное кода все тот же ... вот результат: Example

...