简体   繁体   中英

How do I parse this CSV file since it has to many commas in it has like 3 parts I need to retrive information?

I am practicing to parse text and csv files. I have a particular csv file on witch I have been trying to parse for several hours, but I have unable to find the correct logic to do so since, according to the parsing 19 lines and I need to retrive cetain informationon the first 2 lines then I have to show all the info bellow. The csv file looks like this

Titular,Cuenta #,Moneda,Fecha del reporte,,
MyCompany,123654897,Dollar,26/6/2010,,
,,,,,
Períod,,,,,
From:,31/01/2010,Until:,25/06/2019,,
,,,,,
Date,Description,Númber reference,Débit,Crédit,Balance
31/01/2019,Credito por Intereses,710504251714-50398277,,132.16,"3,073.55"
8/2/2019,Depositos,S9091B19,,"74,258.74","9,722.29"
8/2/2019,ACH Debito,F1999ZV,"8,748.35",,"2,073.55"
14/02/2019,Creditos Varios,F90BRF,,"7,429.77","4,391.32"
18/02/2019,ACH Debito,FT0SMD,"4,824.77",,"3,073.55"
21/02/2019,ACH Credito,F8PH,,"8,000.98","3,673.53"
21/02/2019,Transferencia entre Cuentas,2DMFRG,"7,005.96",,"2,667.57"
22/02/2019,Pago de Comision,R2SHX,20.00,,"5,647.57"
25/02/2019,ACH Credito,FT1905,,"4,083.08","4,490.65"
25/02/2019,Transferencia entre Cuentas,FT254354,"4,437.10",,"3,053.55"
25/02/2019,ACH Credito,ASF455MZQT,,222.15,"3,675.70"
25/02/2019,Transferencia entre Cuentas,GHVF456Q1XLG,"5,536.33",,"5,453.55"

I have run some test and been debugging to see the behavior and ask my self; Do I need to specify the line that Im in , in order for me to retrieve the info? If so, how dow I do it?

heres my code:

using System;
using System.Collections.Generic;
 using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace T_2060_ParserEstadoDeCuenta
{
 class Program
 {
    static void Main(string[] args)
    {
        Console.WriteLine("Parsing the csv file");

        List<clsEstadoCuenta> resp = new List<clsEstadoCuenta>();
        var lines = File.ReadAllLines("d:\\ztemp\\parseEstcta.csv");
        for (int i = 1; i < lines.Count(); i++)
        {
            try
            {
                /*

                 */
                var campos = lines[i].Split(',');
                clsEstadoCuenta nR = new clsEstadoCuenta();

                nR.NumeroCuenta = (String.IsNullOrEmpty(campos[1])) ? "" : campos[1];
                nR.CodigoPais = 504;
                nR.Banco = "Fichosa";
                nR.Moneda = (String.IsNullOrEmpty(campos[2])) ? "" : campos[2];
                nR.TasaCambio = 24.6;
                var tmpFecha = campos[0].Split('/');
                nR.FechaTransaccion = new DateTime(Convert.ToInt32(tmpFecha[2]), Convert.ToInt32(tmpFecha[1]), Convert.ToInt32(tmpFecha[0]));
                nR.Descripcion = (String.IsNullOrEmpty(campos[1])) ? "" : campos[1];
                nR.Referencia = (String.IsNullOrEmpty(campos[2])) ? "" : campos[2];
                nR.Debito = (String.IsNullOrEmpty(campos[4])) ? 0 : Convert.ToDouble(campos[4]);
                nR.Credito = (String.IsNullOrEmpty(campos[5])) ? 0 : Convert.ToDouble(campos[5]);
                nR.Payee = "A";




            }
            catch (Exception ex)
            {

                Console.WriteLine("error on line {0} : {1}", i, ex.Message);
                continue;
            }
        }
        Console.WriteLine("Parsing has ended, we have {0} rows \n", resp.Count);

        foreach (var item in resp)
        {

            Console.WriteLine(item.NumeroCuenta+"\t" +item.CodigoPais+"\t"+item.Banco+"t"+item.Moneda+"\t"+item.Debito);
        }
        Console.ReadLine();
    }

    class clsEstadoCuenta
    {
        private string _NumeroCuenta;

        public string NumeroCuenta
        {
            get { return _NumeroCuenta; }
            set { _NumeroCuenta = value; }
        }
        private int _CodigoPais;

        public int CodigoPais
        {
            get { return _CodigoPais; }
            set { _CodigoPais = value; }
        }

        private string _Banco;

        public string Banco
        {
            get { return _Banco; }
            set { _Banco = value; }
        }

        private string _Moneda;

        public string Moneda
        {
            get { return _Moneda; }
            set { _Moneda = value; }
        }

        private double _TasaCambio;

        public double TasaCambio
        {
            get { return _TasaCambio; }
            set { _TasaCambio = value; }
        }

        private double _Debito;

        public double Debito
        {
            get { return _Debito; }
            set { _Debito = value; }
        }

        private double _Credito;

        public double Credito
        {
            get { return _Credito; }
            set { _Credito = value; }
        }

        private DateTime _FechaTrasaccion;

        public DateTime FechaTransaccion
        {
            get { return _FechaTrasaccion; }
            set { _FechaTrasaccion = value; }
        }

        private string _Payee;

        public string Payee
        {
            get { return _Payee; }
            set { _Payee = value; }
        }

        private string _Descripcion;

        public string Descripcion
        {
            get { return _Descripcion; }
            set { _Descripcion = value; }
        }

        private string _Referencia;

        public string Referencia
        {
            get { return _Referencia; }
            set { _Referencia = value; }
        }

        private string _CodigoBancario;

        public string CodigoBancario
        {
            get { return _CodigoBancario; }
            set { _CodigoBancario = value; }
        }

        private string _Categoria;

        public string Categoria
        {
            get { return _Categoria; }
            set { _Categoria = value; }
        }

        private string _Sector;

        public string Sector
        {
            get { return _Sector; }
            set { _Sector = value; }
        }

        private double _ValorLocal;

        public double ValorLocal
        {
            get
            {
                _ValorLocal = Credito - Debito;
                return _ValorLocal;
            }
            //set { _ValorLocal = value; }
        }

        private double _ValorDolares;

        public double ValorDolares
        {
            get
            {
                _ValorDolares = ValorLocal / TasaCambio;
                return _ValorDolares;
            }
           // set { _ValorDolares = value; }
        }

        private string _NombreEmpresa;

        public string NombreEmpresa
        {
            get { return _NombreEmpresa; }
            set { _NombreEmpresa = value; }
        }

    }
  }
}

The issue is that you try to separate the cells by splitting ',' but part of the cells contains ',' char. Example: "9,722.29".

Although the formatting of this CSV is not the best, since it mixes numbers with comma and dot and the separation of fields is comma. Still it is possible to work with it, it is only necessary a little logic to reassemble the numbers that will be separated with the lines.Split(',') .

Below is the example that lists the data on the screen and adds the values in the clsEstadoCuenta .

The logic to mount the broken numbers is this.

     if (!string.IsNullOrEmpty(campos[i]))
     {
         if (campos[i][0] == '\"')
         {
             campos[i] = campos[i] + campos[i + 1];
             campos[i + 1] = "";
             campos[i] = campos[i].Replace("\"","");
         }
     }

When he goes through the fields he checks the broken one and if he is he takes the rest of the value in the next field and joins the two.

Here is the complete code below.

    static void Main(string[] args)
    {
        ReadCsv();

        Console.WriteLine("...");
        Console.ReadLine();
    }

    private static void ReadCsv()
    {
        string desk = System.IO.Directory.GetParent(@"../../").FullName;
        String path = $@"{desk}\filecsv.csv";
        var csvlines = File.ReadAllLines(path);

        Console.WriteLine("Parsing the csv file");


        //build header
        var header = csvlines[1].Split(',');

        clsEstadoCuenta nR = new clsEstadoCuenta();
        nR.NumeroCuenta = (String.IsNullOrEmpty(header[1])) ? "" : header[1];
        nR.CodigoPais = 504;
        nR.Banco = "Fichosa";
        nR.Moneda = (String.IsNullOrEmpty(header[2])) ? "" : header[2];
        nR.TasaCambio = 24.6;


        //build list of data
        foreach (var lines in csvlines.Skip(7))
        {
            var campos = lines.Split(',');

            //mount line
            string newline = "";
            for (int i = 0; i < campos.Count(); i++)
            {
                //Here the numbers that were divided by the Spli (',') 
                //are reassembled and saved in their respective fields.
                if (!string.IsNullOrEmpty(campos[i]))
                {
                    if (campos[i][0] == '\"')
                    {
                        campos[i] = campos[i] + campos[i + 1];
                        campos[i + 1] = "";
                        campos[i] = campos[i].Replace("\"","");
                    }
                }

                newline += $"{campos[i]} \t";
            }

            //puts the values in the clsEstadoCuenta
            var tmpFecha = campos[0].Split('/');
            nR.FechaTransaccion = new DateTime(Convert.ToInt32(tmpFecha[2]), Convert.ToInt32(tmpFecha[1]), Convert.ToInt32(tmpFecha[0]));
            nR.Descripcion = (String.IsNullOrEmpty(campos[1])) ? "" : campos[1];
            nR.Referencia = (String.IsNullOrEmpty(campos[2])) ? "" : campos[2];
            nR.Debito = (String.IsNullOrEmpty(campos[4])) ? 0 : Convert.ToDouble(campos[4]);
            nR.Credito = (String.IsNullOrEmpty(campos[5])) ? 0 : Convert.ToDouble(campos[5]);
            nR.Payee = "A";

            Console.WriteLine($"{newline}");
        }
    }

SOLUTION 2

This code needs some modifications to work correctly some of the attributes of clsStateCount.cs will need to be List and then yes may be Add() such as nR.Debito.Add()

The class clsStateCount.cs will need a constructor that creates the Lists .

    public clsEstadoCuenta()
    {
        _FechaTrasaccion = new List<DateTime>();
        _Descripcion = new List<string>();
        _Referencia = new List<string>();
        _Payee = new List<string>();
        _Debito = new List<double>();
        _Credito = new List<double>();
        _Payee = new List<string>();
    }

Also the Date , Description , Númber Reference , Débit , Crédit and Balance attributes will need to be List since they will receive several data.

    private List<DateTime> _FechaTrasaccion;
    public List<DateTime> FechaTransaccion
    {
        get { return _FechaTrasaccion; }
        set { _FechaTrasaccion = value; }
    }

Here is the complete code for Class:

class clsEstadoCuenta
{

    //you will need a builder to create the lists
    public clsEstadoCuenta()
    {
        _FechaTrasaccion = new List<DateTime>();
        _Descripcion = new List<string>();
        _Referencia = new List<string>();
        _Payee = new List<string>();
        _Debito = new List<double>();
        _Credito = new List<double>();
        _Payee = new List<string>();
    }


    //method GetTransactionsNumber() 
    //heck how many items there are in the lists below
    public int GetTransactionsNumber()
    {
        return _FechaTrasaccion.Count;
    }


    //the methods below will be List since it 
    //will receive several values
    private List<DateTime> _FechaTrasaccion;
    public List<DateTime> FechaTransaccion
    {
        get { return _FechaTrasaccion; }
        set { _FechaTrasaccion = value; }
    }

    private List<string> _Descripcion;
    public List<string> Descripcion
    {
        get { return _Descripcion; }
        set { _Descripcion = value; }
    }

    private List<string> _Referencia;
    public List<string> Referencia
    {
        get { return _Referencia; }
        set { _Referencia = value; }
    }

    private List<double> _Debito;
    public List<double> Debito
    {
        get { return _Debito; }
        set { _Debito = value; }
    }

    private List<double> _Credito;
    public List<double> Credito
    {
        get { return _Credito; }
        set { _Credito = value; }
    }

    private List<string> _Payee;
    public List<string> Payee
    {
        get { return _Payee; }
        set { _Payee = value; }
    }



    //private double _ValorLocal;
    //public double ValorLocal
    //{
    //    get
    //    {
    //        _ValorLocal = Credito - Debito;
    //        return _ValorLocal;
    //    }
    //    //set { _ValorLocal = value; }
    //}

    //private double _ValorDolares;
    //public double ValorDolares
    //{
    //    get
    //    {
    //        _ValorDolares = ValorLocal / TasaCambio;
    //        return _ValorDolares;
    //    }
    //    // set { _ValorDolares = value; }
    //}




    private string _NumeroCuenta;
    public string NumeroCuenta
    {
        get { return _NumeroCuenta; }
        set { _NumeroCuenta = value; }
    }
    private int _CodigoPais;
    public int CodigoPais
    {
        get { return _CodigoPais; }
        set { _CodigoPais = value; }
    }

    private string _Banco;
    public string Banco
    {
        get { return _Banco; }
        set { _Banco = value; }
    }

    private string _Moneda;
    public string Moneda
    {
        get { return _Moneda; }
        set { _Moneda = value; }
    }

    private double _TasaCambio;
    public double TasaCambio
    {
        get { return _TasaCambio; }
        set { _TasaCambio = value; }
    }

    private string _NombreEmpresa;
    public string NombreEmpresa
    {
        get { return _NombreEmpresa; }
        set { _NombreEmpresa = value; }
    }

    private string _CodigoBancario;
    public string CodigoBancario
    {
        get { return _CodigoBancario; }
        set { _CodigoBancario = value; }
    }

    private string _Categoria;
    public string Categoria
    {
        get { return _Categoria; }
        set { _Categoria = value; }
    }

    private string _Sector;
    public string Sector
    {
        get { return _Sector; }
        set { _Sector = value; }
    }
}

Already the code that reads CSV and what displays I put with separate functions to make it easier to see.

    static void Main(string[] args)
    {
        ReadCsvList();

        Console.WriteLine("...");
        Console.ReadLine();
    }


    private static void ReadCsvList()
    {
        string desk = System.IO.Directory.GetParent(@"../../").FullName;
        String path = $@"{desk}\filecsv.csv";
        var csvlines = File.ReadAllLines(path);


        //build header
        var header = csvlines[1].Split(',');

        clsEstadoCuenta nR = new clsEstadoCuenta();
        nR.NumeroCuenta = (String.IsNullOrEmpty(header[1])) ? "" : header[1];
        nR.CodigoPais = 504;
        nR.Banco = "Fichosa";
        nR.Moneda = (String.IsNullOrEmpty(header[2])) ? "" : header[2];
        nR.TasaCambio = 24.6;


        //build list of data
        foreach (var lines in csvlines.Skip(7))
        {
            var campos = lines.Split(',');

            //mount line
            string newline = "";
            for (int i = 0; i < campos.Count(); i++)
            {
                //Here the numbers that were divided by the Spli (',') 
                //are reassembled and saved in their respective fields.
                if (!string.IsNullOrEmpty(campos[i]))
                {
                    if (campos[i][0] == '\"')
                    {
                        campos[i] = campos[i] + campos[i + 1];
                        campos[i + 1] = "";
                        campos[i] = campos[i].Replace("\"", "");
                    }
                }

                newline += $"{campos[i]} \t";
            }

            //puts the values in the clsEstadoCuenta
            var tmpFecha = campos[0].Split('/');
            nR.FechaTransaccion.Add(new DateTime(Convert.ToInt32(tmpFecha[2]), Convert.ToInt32(tmpFecha[1]), Convert.ToInt32(tmpFecha[0])));
            nR.Descripcion.Add(String.IsNullOrEmpty(campos[1]) ? "" : campos[1]);
            nR.Referencia.Add(String.IsNullOrEmpty(campos[2]) ? "" : campos[2]);
            nR.Debito.Add(String.IsNullOrEmpty(campos[4]) ? 0 : Convert.ToDouble(campos[4]));
            nR.Credito.Add(String.IsNullOrEmpty(campos[5]) ? 0 : Convert.ToDouble(campos[5]));
            nR.Payee.Add("A");
        }

        //I will only display on the screen in 
        //this function below, it gets cleaner code.
        ListDataCSV(nR);
    }

    private static void ListDataCSV(clsEstadoCuenta data)
    {
        Console.WriteLine("Parsing the csv file");

        Console.WriteLine($"Conta: {data.NumeroCuenta} \t Pais: {data.CodigoPais} \t Banco: {data.Banco}");
        Console.WriteLine($"Moeda: {data.Moneda} \t\t Cambio: {data.TasaCambio}");

        Console.WriteLine($"");
        Console.WriteLine($"Date \t\t Description \t\t Númber Reference \t\t Débit \t Crédit \t Balance");

        for (int i = 0; i < data.GetTransactionsNumber(); i++)
        {
            var vdata = data.FechaTransaccion[i].ToString("dd/MM/yy HH:mm");
            var vdescription = data.Descripcion[i];
            var vreference = data.Referencia[i];
            var vdebito = data.Debito[i];
            var vcredito = data.Credito[i];
            var vpayee = data.Payee[i];

            Console.WriteLine($"{vdata} \t {vdescription} \t\t {vreference} \t\t {vdebito} \t {vcredito} \t {vpayee}");
        }
    }

Use a CSV parser that adheres to RFC 4180 - Common Format and MIME Type for CSV Files .

It is important to understand that the usage of double quotes in your example CSV is likely to handle cases like "74,258.74" where the comma is not to be used as a delimiter. As stated by the standard:

Each field may or may not be enclosed in double quotes (however some programs, such as Microsoft Excel, do not use double quotes at all). If fields are not enclosed with double quotes, then double quotes may not appear inside the fields. For example:

  "aaa","bbb","ccc" zzz,yyy,xxx 

Here is the Getting Started page for the most popular compliant parser on NuGet .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM