Заголовки столбцов в CSV с использованием библиотеки filesHelpers?
Есть ли встроенный атрибут поля в библиотеке FileHelper, который добавит строку заголовка в окончательный сгенерированный CSV?
У меня есть Googled и не нашел много информации об этом. В настоящее время у меня есть это:
DelimitedFileEngine _engine = new DelimitedFileEngine(T);
_engine.WriteStream
(HttpContext.Current.Response.Output, dataSource, int.MaxValue);
Он работает, но без заголовка.
Я подумываю иметь атрибут типа FieldTitleAttribute
и использовать его как заголовок столбца.
Итак, мой вопрос в какой момент я проверяю атрибут и вставляю столбцы заголовков? Кто-нибудь сделал что-то подобное раньше?
Я бы хотел, чтобы заголовки вставили и использовали пользовательский текст, отличный от фактического имени поля, просто используя атрибут для каждого члена объекта:
[FieldTitleAttribute("Custom Title")]
private string Name
и, возможно, возможность указать движку вставить заголовок при его создании.
Поэтому, когда вызывается WriteStream
или WriteString
, строка заголовка будет вставлена с использованием пользовательских заголовков.
Я нашел пару событий для DelimitedFileEngine, но не лучший способ определить, является ли текущая запись первой строкой и как вставить строку до этого.
Ответы
Ответ 1
Вот код, который это сделает: https://gist.github.com/1391429
Чтобы использовать его, вы должны украсить свои поля [FieldOrder]
(в любом случае, хорошая практика FileHelpers). Использование:
[DelimitedRecord(","), IgnoreFirst(1)]
public class Person
{
// Must specify FieldOrder too
[FieldOrder(1), FieldTitle("Name")]
string name;
[FieldOrder(2), FieldTitle("Age")]
int age;
}
...
var engine = new FileHelperEngine<Person>
{
HeaderText = typeof(Person).GetCsvHeader()
};
...
engine.WriteFile(@"C:\people.csv", people);
Но поддержка этого действительно должна быть добавлена в самих FileHelpers. Я могу придумать несколько вопросов дизайна от верхней части головы, которые должны были бы ответить, прежде чем они могут быть реализованы:
- Что происходит при чтении файла? Afaik FileHelpers в настоящее время все основывается на порядковой позиции столбца и игнорирует имена столбцов... но если теперь у нас есть атрибуты
[FieldHeader]
, то следует ли нам также попробовать сопоставить свойства с именами столбцов в файле? Следует ли исключить исключение, если они не совпадают? Что произойдет, если порядковая позиция не согласуется с именем столбца?
- При чтении в качестве таблицы данных следует использовать A) имя поля (текущий проект) или B) имя столбца исходного файла или C) атрибут FieldTitle?
Ответ 2
Я знаю, что это старый вопрос, но вот ответ, который работает для v2.9.9
FileHelperEngine<Person> engine = new FileHelperEngine<Person>();
engine.HeaderText = engine.GetFileHeader();
Ответ 3
Я не знаю, нужна ли вам эта проблема, но вот как работает FileHelper:
Чтобы включить заголовки столбцов, вам необходимо определить строку с заголовками, разделенными так же, как и ваш файл.
Например, с '|' в качестве разделителя:
public const string HeaderLine = @"COLUMN1|COLUMN2|COLUMN3|...";
Затем при вызове вашего движка:
DelimitedFileEngine _engine = new DelimitedFileEngine<T> { HeaderText = HeaderLine };
Если вы не хотите писать заголовки, просто не устанавливайте атрибут HeaderText
в движке.
Ответ 4
List<MyClass> myList = new List<MyClass>();
FileHelperEngine engine = new FileHelperEngine(typeof(MyClass));
String[] fieldNames = Array.ConvertAll<FieldInfo, String>(typeof(MyClass).GetFields(), delegate(FieldInfo fo) { return fo.Name; });
engine.HeaderText = String.Join(";", fieldNames);
engine.WriteFile(MapPath("MyClass.csv"), myList);
Ответ 5
Я обнаружил, что вы можете использовать FileHelperAsyncEngine, чтобы выполнить это. Предполагая, что ваши данные представляют собой список "output" типа "outputData", вы можете написать код, который выглядит так:
FileHelperAsyncEngine outEngine = new FileHelperAsyncEngine(typeof(outputData));
outEngine.HeaderText = "Header1, Header2, Header3";
outEngine.BeginWriteFile(outputfile);
foreach (outputData line in output){
outEngine.WriteNext(line);
}
outEngine.Close();