c# - delimitedrecord - ¿Encabezados de columna en CSV usando la biblioteca de archivos de herramientas?
csv reader c# (5)
¿Hay un atributo de campo incorporado en la biblioteca FileHelper que agregará una fila de encabezado en el CSV generado final?
Busqué en Google y no encontré mucha información sobre él. Actualmente tengo esto:
DelimitedFileEngine _engine = new DelimitedFileEngine(T);
_engine.WriteStream
(HttpContext.Current.Response.Output, dataSource, int.MaxValue);
Funciona, pero sin un encabezado.
Estoy pensando en tener un atributo como FieldTitleAttribute
y usar esto como un encabezado de columna.
Entonces, mi pregunta es en qué punto verifico el atributo e inserto las columnas del encabezado? ¿Alguien ha hecho algo similar antes?
Me gustaría insertar los encabezados y usar texto personalizado diferente del nombre real del campo con solo tener un atributo en cada miembro del objeto:
[FieldTitleAttribute("Custom Title")]
private string Name
y tal vez una opción para decirle al motor que inserte el encabezado cuando se genera.
Por lo tanto, cuando se WriteStream
o WriteString
, la fila del encabezado se insertará con títulos personalizados.
He encontrado un par de eventos para DelimitedFileEngine, pero no cuál es la mejor manera de detectar si el registro actual es la primera fila y cómo insertar una fila antes de esto.
Aquí hay un código que lo hará: https://gist.github.com/1391429
Para usarlo, debe decorar sus campos con [FieldOrder]
(una buena práctica de FileHelpers de todos modos). Uso:
[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);
Pero el soporte para esto realmente necesita ser agregado dentro de FileHelpers. Puedo pensar en algunas preguntas de diseño de la parte superior de mi cabeza que necesitarían respuesta antes de que puedan implementarse:
- ¿Qué sucede cuando lee un archivo? Actualmente, Afaik FileHelpers se basa en la posición de la columna ordinal e ignora los nombres de las columnas ... pero si ahora tenemos los atributos de
[FieldHeader]
todas partes, ¿deberíamos intentar también[FieldHeader]
propiedades con nombres de columna en el archivo? ¿Deberías lanzar una excepción si no coinciden? ¿Qué sucede si la posición ordinal no concuerda con el nombre de la columna? - Al leer como una tabla de datos, ¿debería usar A) el nombre del campo (diseño actual), o B) el nombre de la columna del archivo fuente, o C) el atributo FieldTitle?
Descubrí que puedes usar el FileHelperAsyncEngine para lograr esto. Suponiendo que sus datos son una lista llamada "salida" de tipo "outputData", entonces puede escribir código que se ve así:
FileHelperAsyncEngine outEngine = new FileHelperAsyncEngine(typeof(outputData));
outEngine.HeaderText = "Header1, Header2, Header3";
outEngine.BeginWriteFile(outputfile);
foreach (outputData line in output){
outEngine.WriteNext(line);
}
outEngine.Close();
No sé si todavía necesita esto, pero así es como funciona FileHelper: para incluir encabezados de columnas, debe definir una cadena con encabezados delimitados de la misma manera que su archivo. Por ejemplo, con ''|'' como delimitador:
public const string HeaderLine = @"COLUMN1|COLUMN2|COLUMN3|...";
Luego, cuando llame a su motor:
DelimitedFileEngine _engine = new DelimitedFileEngine<T> { HeaderText = HeaderLine };
Si no desea escribir los encabezados, simplemente no configure el atributo HeaderText
en el motor.
Sé que esta es una vieja pregunta, pero aquí hay una respuesta que funciona para v2.9.9
FileHelperEngine<Person> engine = new FileHelperEngine<Person>();
engine.HeaderText = engine.GetFileHeader();
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);