Cómo importar datos de archivos Excel con C#

Es muy habitual en cualquier proyecto, que se nos demande la característica de importar información de otros archivos. Este proceso suele ser tal que así: cargamos los datos de algún archivo, validamos y corregimos la información y la procesamos.

Los desarrolladores a menudo tienen diferentes opiniones en cuanto a qué librería es mejor para cargar los datos de un fichero. Pero, ¿es esto lo más importante? ¿Qué pasa si en la importación tenemos que soportar diferentes tipos de archivos? Por ejemplo: .csv, .xls, .xlsx.

En mi opinión, no es tan importante el cómo cargar los datos, sino lo que vamos a hacer con ellos después. Es por eso que surgió la idea de desarrollar una solución que nos permita olvidarnos de cómo cargar los datos desde un archivo en la memoria, y centrarnos en el procesamiento de dichos datos.

Cómo utilizar el código

La mejor manera de saber cómo utilizar esta librería es analizar el proyecto Fileo.Tests incluido en la solución Fileo. Aquí tienes algunos ejemplos.

Crea una clase con información sobre la estructura de archivos importada. Especifica los tipos de columnas individuales y establece las validaciones. Por ejemplo:

internal class Test1ImportFileStructure : ImportFileStructureBase
{
    private readonly string[] _dateTimeFormats = { "dd/MM/yyyy"};
    private readonly CultureInfo _cultureInfo = new CultureInfo("en-GB");
    private const string CustomRegularExpression = "^(Y|N)+$";

    public override IList Columns => new List
    {
        Column.CreateIdentityStringColumn(Test1Columns.Col1String, 0, 5),
        Column.CreateStringColumn(Test1Columns.Col2StringNull, 1, false, 5),
        Column.CreateIntColumn(Test1Columns.Col3Int, 2, true),
        Column.CreateIntColumn(Test1Columns.Col4IntNull, 3, false, -90, 90),
        Column.CreateDateTimeColumn(Test1Columns.Col5DateTime, 4, true, _dateTimeFormats),
        Column.CreateDateTimeColumn(Test1Columns.Col6DateTimeNull, 5, false, _dateTimeFormats),
        Column.CreateDecimalColumn(Test1Columns.Col7Decimal, 6, true, _cultureInfo, 0, 10),
        Column.CreateDecimalColumn(Test1Columns.Col8DecimalNull, 7, false, _cultureInfo, 0, 100),
        Column.CreateBoolColumn(Test1Columns.Col9Bool, 8, true),
        Column.CreateBoolColumn(Test1Columns.Col10BoolNull, 9, false),
        Column.CreateStringColumn(Test1Columns.Col11Email, 10, true, 100, RegexValidation.Email),
        Column.CreateStringColumnWithCustomRegex(Test1Columns.Col12CustomRegex, 11, 
                                true, 1, CustomRegularExpression),
    };

Crea una clase que represente una fila del archivo. Por ejemplo:

public class Test1ImportResult
{
    public string Col1String { get; set; }
    public string Col2StringNull { get; set; }
    public int Col3Int { get; set; }
    public int? Col4IntNull { get; set; }
    public DateTime Col5DateTime { get; set; }
    public DateTime? Col6DateTimeNull { get; set; }
    public decimal Col7Decimal { get; set; }
    public decimal? Col8DecimalNull { get; set; }
    public bool Col9Bool { get; set; }
    public bool? Col10BoolNull { get; set; }
    public string Col11Email { get; set; }
    public string Col12CustomRegex { get; set; }
}    

Crea una clase genérica que represente todos los datos importados. Por ejemplo:

public class ImportResult< T>
{
    public IList< string> Errors { get; }
    public bool HasErrors { get { return !Errors.IsNullOrEmpty() && Errors.Any(); } }
    public IList< T> Objects { get; private set; }

    public ImportResult(IList< T> objects, IList< string> errors)
    {
        Objects = objects;
        Errors = errors;
    }
}

Crea una clase que parsee los datos del archivo a tu clase (desde el punto 2). Por ejemplo:

internal class Test1Import
{
    private readonly Table _fileDataInternal;

    public Test1Import(Table fileData)
    {
        _fileDataInternal = fileData;
        Validate();
    }

    public ImportResult< Test1ImportResult> Import()
    {
        var objects = _fileDataInternal.CorrectRows.Select(row => new Test1ImportResult
        {
            Col1String = row.GetStringValue(Test1Columns.Col1String, true),
            Col2StringNull = row.GetStringValue(Test1Columns.Col2StringNull, false),
            Col3Int = row.GetIntValue(Test1Columns.Col3Int),
            Col4IntNull = row.GetNullableIntValue(Test1Columns.Col4IntNull),
            Col5DateTime = row.GetDateValue(Test1Columns.Col5DateTime),
            Col6DateTimeNull = row.GetNullableDateValue(Test1Columns.Col6DateTimeNull),
            Col7Decimal = row.GetDecimalValue(Test1Columns.Col7Decimal),
            Col8DecimalNull = row.GetNullableDecimalValue(Test1Columns.Col8DecimalNull),
            Col9Bool = row.GetBoolValue(Test1Columns.Col9Bool),
            Col10BoolNull = row.GetNullableBoolValue(Test1Columns.Col10BoolNull),
            Col11Email = row.GetStringValue(Test1Columns.Col11Email, true),
            Col12CustomRegex = row.GetStringValue(Test1Columns.Col12CustomRegex, true)
        }).ToList();

        var result = new ImportResult< Test1ImportResult>(objects, _fileDataInternal.GetErrors());
        return result;
    }

    private void Validate()
    {
        if (_fileDataInternal == null)
        {
            throw new ArgumentNullException("fileData");
        }
    }
} 

Crea una clase que contenga métodos que utilizarán Fileo para analizar el archivo (.csv, .xls, .xlsx) en su clase.

public static class Imports
{
    public static ImportResult< Test1ImportResult> 
    ImportTest1(HttpPostedFileBase httpPostedFileBase)
    {
        var fileData = ImporterHelper.ImportFromFile
                       (httpPostedFileBase, new Test1ImportFileStructure());
        var venuesImport = new Test1Import(fileData);
        return venuesImport.Import();
    }
}

Llama a los métodos (desde el punto 5) y obtendrás tus datos.

Fuente: kw677

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP