2010-10-20 8 views
45

¿Hay un atributo de campo incorporado en la biblioteca FileHelper que agregará una fila de encabezado en el CSV generado final?Encabezados de columna en CSV utilizando la biblioteca de archivos de herramientas?

He buscado en Google y no he encontrado mucha información al respecto. 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 utilizar 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 obtener las cabeceras insertadas y utilizar un texto personalizado diferente del nombre real del campo sólo por tener un atributo para cada miembro del objeto:

[FieldTitleAttribute("Custom Title")] 
private string Name 

y tal vez una opción de decir que el motor inserte el encabezado cuando se genera.

Así que cuando se llama a 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.

Respuesta

29

Aquí hay un código que 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 la compatibilidad con esto realmente debe agregarse dentro de FileHelpers. Puedo pensar en algunas preguntas de diseño que deberían responder antes de implementarse:

  • ¿Qué ocurre cuando se 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 [FieldHeader] en todas partes, ¿deberíamos probar también las propiedades coincidentes con los 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 de campo (diseño actual) o B) el nombre de la columna del archivo fuente, o C) el atributo FieldTitle?
+0

gracias por compartir y buen trabajo allí. ¿Desea agregar en la clase 'FieldOrderAttribute' por completo? – Heinnge

+2

@Heinnge La clase FieldOrderAttribute se encuentra en la biblioteca FileHelpers 2.9.9.0. –

+0

¿Cómo responde esto la pregunta dado que FieldOrder no agrega un encabezado de columna? –

23

No sé si todavía necesita esto, pero esta es la forma en que FileHelper está funcionando: 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|..."; 

Entonces, cuando se llama a su motor:

DelimitedFileEngine _engine = new DelimitedFileEngine<T> { HeaderText = HeaderLine }; 

Si no desea escribir los encabezados, simplemente no se establece el atributo HeaderText en el motor.

+0

gracias Saaman. Termino escribiendo un atributo personalizado para esto y métodos de extensión adicionales que generaron la columna del encabezado. – Heinnge

+0

@Heinnge, ¿publicaste el código para esto en cualquier lugar? – CDeutsch

+1

@CDeutsc Ya no tengo el código. Pero creé un atributo simple [FieldTitleAttribute ("Título personalizado")], deshabilité los encabezados de buildin y recreé el encabezado con título personalizado (si lo hubiera) de lo contrario con los nombres de campo predeterminados. – Heinnge

1

Encontré que puede usar el FileHelperAsyncEngine para lograr esto. Suponiendo sus datos es una lista llamada "salida" de tipo "datosSalida", entonces se puede escribir código que se parece a esto:

 FileHelperAsyncEngine outEngine = new FileHelperAsyncEngine(typeof(outputData)); 
     outEngine.HeaderText = "Header1, Header2, Header3"; 
     outEngine.BeginWriteFile(outputfile); 
     foreach (outputData line in output){ 
      outEngine.WriteNext(line); 
     } 
     outEngine.Close(); 
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); 
+2

Una construcción ligeramente más simple para obtener los nombres de los campos: var headerText = String.Join (",", typeof (MyClass) .GetFields(). Seleccione (f => f.Name) .ToList()); FileHelperEngine engine = new FileHelperEngine () {HeaderText = headerText}; –

35

Sé que esto es una vieja pregunta, pero aquí es una respuesta que trabaja para v2.9.9

FileHelperEngine<Person> engine = new FileHelperEngine<Person>(); 
engine.HeaderText = engine.GetFileHeader(); 
+0

También es el enfoque recomendado en sus preguntas frecuentes: http://www.filehelpers.net/mustread/ en "Quiero escribir un archivo con encabezados" – Colin

+0

Relacionados: http://stackoverflow.com/a/8833322/109941 –

+2

Esta debería ser la respuesta seleccionada. – Jaxidian

Cuestiones relacionadas