Delphi => C#: generic function to return billet DV

Asked

Viewed 333 times

-1

I’m having problems with a custom Module 11 function (which correctly returns the billet dv of any bank) that already had it in Delphi, and how I’m needing it to implement in a C system#.

So I tried to make the C# version of it, but it has logic error or syntax, since I don’t have much affinity with C#.

It is worth noting that from the sequential flow point of view compared to the Delphi version, in my opinion, is correct.

Follows:

     /// <summary>
    /// Remove a primeira ocorrência da substring em uma string completa
    /// </summary>
    /// <param name="source">String completa</param>
    /// <param name="remove">String para ser removida</param>
    /// <returns>Retorna a nova string sem os caracteres que foram retirados</returns>

    public static string RemoveFirst(this string source, string remove)
    {
        int index = source.IndexOf(remove);
        return (index < 0)
            ? source
            : source.Remove(index, remove.Length);
    }


            /// <summary>
            /// Valida o dígito verificador da linha digitável
            /// </summary>
            /// <param name="Valor">Linha Digitável</param>
            /// <param name="Base"></param>
            /// <param name="Resto"></param>
            /// <returns>Retorna o dígito verificador correspondente a linha digitável avaliada</returns>

            public static string Modulo11LinhaDigitavel(string Valor, int Base = 9, bool Resto = false)
            {

                int peso = 2;
                int soma = 0;
                int contador, digito, i;
                string retorno = "";

                for (i = 1; i <= Valor.Length; i++)
                {
                    int pos = Valor[i].ToString().IndexOf("0123456789");

                    if (pos < 0)

                        RemoveFirst(Valor, Valor[i].ToString());

                }

                Valor = Valor.Substring(0, 4) + // 1 e 4
                              Valor.Substring(32, 15) + // 33 e 15
                              Valor.Substring(4, 5) +  // 5 e 5
                              Valor.Substring(10, 10) + // 11 e 10
                              Valor.Substring(21, 10); // 22 e 10

                                                   // 1 e 4                    // 6 e 39
                Valor = Valor.Substring(0, 4) + Valor.Substring(5, 39);

                for (contador = Valor.Length; contador >= 0; contador--)
                {
                    soma = soma + (Convert.ToInt32(Valor[contador]) * peso);

                    if (peso < Base)
                    {
                        peso = peso + 1;
                    }
                    else
                    {
                        peso = 2;
                    }
                }

                if (Resto)
                {
                    retorno = (soma % 11).ToString();
                    return retorno;
                }
                else
                {
                    digito = 11 - (soma % 11);

                    if (digito > 9) 
                    { 

                        digito = 0;

                        retorno =  digito.ToString();

                        return retorno;
                    }
                }

                if (retorno == "0") { retorno = "1"; }

                return retorno;
            }

// Uma vez funcionado, teria que retornar 5, que é o DV da linha digitável abaixo em questão        

       static void Main(string[] args)
        {

            Console.WriteLine(Modulo11LinhaDigitavel("10490.05539 03698.700006 00091.449587 5 55490000028531"));
            Console.ReadKey();

        }

The Delphi version can be viewed here

  • But what’s the mistake? What goes wrong?

  • Index was outside the bounds of the array.

  • In which line does it give this? It shows which, not adainta pass the number

  • int pos = Valor[i].ToString().IndexOf("0123456789");

  • Jonas, there is an open source library for generating billets for any bank in Brazil, it is widely used and the community contributes much to keep up to date. Boleto.NET - https://github.com/BoletoNet/boletonet You may want to use it to print, generate shipping and return files, etc. If you don’t want to adopt the entire library, you have the calculation of module 11.

  • How about putting some 2 or 3 examples of digitized lines and the expected results for the operation, who knows how it will be easier to help you.

  • Ready @Richarddias, Hello here the expected result is the same general check digit of the respective lines.

  • @Jonassilva I edited the answer. I had eaten a ball in a row and because I didn’t really understand what a certain command was doing in Delphi, I ended up taking a part that later I saw what I was actually doing. It is now correct and simplified. You can see by running on link that I passed on the answer.

  • @mustache, now yes! Thank you very much. I hope that your solution helps future readers of this issue, because as I said, most of these functions of Module 11 that you have on the Internet or all (except this solution there) do not work as it should.

Show 4 more comments

1 answer

3


Not to be without any answer I gave an improved one. I fixed some mistakes. There were things that the translation of the code was completely wrong, or had performance problems, and the style was not C#. I had unnecessary things, too. It may not be the desired result, but now at least runs without error and has a better base to debug and find if there is something wrong. It stayed like this:

public static string Modulo11LinhaDigitavel(string valor, int digitoBase = 9, bool resto = false) {
    var linha = new StringBuilder(valor.Length);
    for (var i = 0; i < valor.Length; i++) {
        if ("0123456789".IndexOf(valor[i]) >= 0) {
            linha.Append(valor.Substring(i, 1));
        }
    }
    var linhaOrdenada = linha.ToString();
    linhaOrdenada = linhaOrdenada.Substring(0, 4) + 
                    linhaOrdenada.Substring(32, 15) + 
                    linhaOrdenada.Substring(4, 5) +  
                    linhaOrdenada.Substring(10, 10) + 
                    linhaOrdenada.Substring(21, 10); 
    linhaOrdenada = linhaOrdenada.Substring(0, 4) + linhaOrdenada.Substring(5, 39);
    var soma = 0;
    var peso = 2;
    for (var i = linhaOrdenada.Length - 1; i >= 0; i--) {
        soma += Convert.ToInt32(linhaOrdenada.Substring(i, 1)) * peso;
        if (peso < digitoBase) {
            peso++;
        } else {
            peso = 2;
        }
    }
    var retorno = "";
    if (resto) {
        retorno = (soma % 11).ToString();
    } else {
        var digito = 11 - (soma % 11);
        if (digito > 9) { 
            digito = 0;
        }
        retorno = digito.ToString();
    }
    if (retorno == "0") { return "1"; }
    return retorno;
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

Taking the manual and making your own code can be a lot less work. This algorithm is not good, it could be done better.

  • Did you see the result there? the DV was supposed to be 5 and returns 6. It’s not wrong this is not? :-)

  • It must be, but I did what I could with what you showed. Now only if I take the manual and do it for you. Or make a full code translation service. It is not the purpose of the website.

  • It didn’t work no :D, t coming out different results for other billets that have the line in this same format. But thanks for the help.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.