Помогите преобразовать общий List‹T› в электронную таблицу Excel

Я пытаюсь создать функцию, которая принимает общий List<T> и повторяет список, возвращая файл excel byte[]. Функция должна уметь определять свойства объектов. Поэтому, если я передаю List<person> и у человека есть свойства first, last, age и т. д., мне нужно иметь возможность определить имена свойств, чтобы создать заголовки столбцов excel, а затем мне нужно повторить список, чтобы присвоить значения свойств для ячейки столбца. Может ли кто-нибудь указать мне пример кода для работы с List<T> в универсальной функции?


person Kevin McPhail    schedule 02.12.2009    source источник


Ответы (3)


Кроме того: для возврата столбцов в известном порядке: нет определенного порядка для элементов, кроме того, который вы создаете. Например (из MSDN):

Метод GetProperties не возвращает свойства в определенном порядке, например в алфавитном порядке или в порядке объявления. Ваш код не должен зависеть от порядка, в котором возвращаются свойства, потому что этот порядок может меняться.

Если вам не нужно полагаться на порядок, подойдет либо отражение, либо TypeDescriptor; например (отмечая, что это пишет текст TSV, а не byte[] - моя интерпретация заключается в том, что проблема заключается в получении данных, а не в записи Excel):

static void WriteTsv<T>(this IEnumerable<T> data, TextWriter output)
{
    PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
    foreach (PropertyDescriptor prop in props)
    {
        output.Write(prop.DisplayName); // header
        output.Write("\t");
    }
    output.WriteLine();
    foreach (T item in data)
    {
        foreach (PropertyDescriptor prop in props)
        {
            output.Write(prop.Converter.ConvertToString(
                 prop.GetValue(item)));
            output.Write("\t");
        }
        output.WriteLine();
    }
}

Если вам нужен заказ, вам потребуется:

  • передать его (например, как params string[] propertyNames)
  • использовать атрибуты свойств
  • использовать алфавитный

Описанный выше подход TypeDescriptor имеет следующие преимущества (по сравнению с GetType().GetProperties()):

  • он работает с пользовательскими объектными моделями (например, DataView, если вы используете IList)
  • вы можете настроить реализацию для повышения производительности, например HyperDescriptor (полезно, если вы делаете это много)
person Marc Gravell    schedule 02.12.2009
comment
Я думаю, что Кевин имеет в виду... имена свойств для создания... это... имена свойств, чтобы я мог создавать..., а не отсортированный список имен свойств :) - person Dan F; 02.12.2009
comment
О! Я чувствую себя медленно... Я оставлю это как есть, так как я думаю, что это все еще интересный момент, если вы ожидаете одинаковых результатов каждый раз. Спасибо. - person Marc Gravell; 02.12.2009
comment
Спасибо, Марк, это то, что я искал. - person Kevin McPhail; 02.12.2009

Самый простой способ, вероятно, состоит в том, чтобы преобразовать ваш список в DataTable, затем преобразовать DataTable в электронную таблицу Excel.

Вторая ссылка записывает электронную таблицу непосредственно в ответ ASP.NET, это можно легко адаптировать для возврата byte[].

person Jeremy McGee    schedule 02.12.2009

Используйте интерфейс, поддерживаемый вашей коллекцией, например IEnumerable:

public byte[] Process(IEnumerable input) {
    foreach (var elem in input) {
        foreach (PropertyInfo prop in elem.GetType().GetProperties()) {
            Object value = prop.GetValue(elem, null);
            // add value to byte[]
        }
    }
    return bytes;
}
person jheddings    schedule 02.12.2009