lunes, 25 de enero de 2010

Formatear con separadores de miles una cadena

Hola, ultimamente, he visto esta pregunta tanto en foros de EEUU como de HispanoAmerica, por ello me decido a colgar este pequeño ejemplo en C#, tambien lo disponible en VB por si alguien lo necesita:


Para que funcione correctamente ha de invocarse a la funcion desde el evento KeyUP




CODIGO C#


 public string Puntos(string strValor, int intNumDecimales)
{

    string strAux = null;
    string strComas = null;
    string strPuntos = null;
    int intX = 0;
    bool bolMenos = false;

    strComas = "";
    if (strValor.Length == 0) return "";
    strValor = strValor.Replace(Application.CurrentCulture.NumberFormat.NumberGroupSeparator, "");
    if (strValor.Contains(Application.CurrentCulture.NumberFormat.NumberDecimalSeparator)) {
        strAux = strValor.Substring(0, strValor.LastIndexOf(Application.CurrentCulture.NumberFormat.NumberDecimalSeparator));
        strComas = strValor.Substring(strValor.LastIndexOf(Application.CurrentCulture.NumberFormat.NumberDecimalSeparator) + 1);
    }
    else {
        strAux = strValor;
    }

    if (strAux.Substring(0, 1) == Application.CurrentCulture.NumberFormat.NegativeSign) {
        bolMenos = true;
        strAux = strAux.Substring(1);
    }

    strPuntos = strAux;
    strAux = "";
    while (strPuntos.Length > 3) {
        strAux = Application.CurrentCulture.NumberFormat.NumberGroupSeparator + strPuntos.Substring(strPuntos.Length - 3, 3) + strAux;
        strPuntos = strPuntos.Substring(0, strPuntos.Length - 3);
    }
    if (intNumDecimales > 0) {
        if (strValor.Contains(Application.CurrentCulture.NumberFormat.PercentDecimalSeparator)) {
            strComas = Application.CurrentCulture.NumberFormat.PercentDecimalSeparator + strValor.Substring(strValor.LastIndexOf(Application.CurrentCulture.NumberFormat.PercentDecimalSeparator) + 1);
            if (strComas.Length > intNumDecimales) {
                strComas = strComas.Substring(0, intNumDecimales + 1);
            }
         
        }
    }
    strAux = strPuntos + strAux + strComas;
   

    return strAux;
}




        private void textBox1_KeyUp(object sender, KeyEventArgs e)
        {
            textBox1.Text = Puntos(textBox1.Text, 0);
            textBox1.Select(textBox1.TextLength, 0);
        }


CODIGO VB:

    Public Function Puntos(ByVal strValor As String, ByVal intNumDecimales As Integer) As String

        Dim strAux As String = ""
        Dim strComas As String = ""
        Dim strPuntos As String = ""
        Dim intX As Integer = 0
        Dim bolMenos As Boolean = False

        If strValor.Length = 0 Then
            Return ""
        End If
        strValor = strValor.Replace(Application.CurrentCulture.NumberFormat.NumberGroupSeparator, "")
        If strValor.Contains(Application.CurrentCulture.NumberFormat.NumberDecimalSeparator) Then
            strAux = strValor.Substring(0, strValor.LastIndexOf(Application.CurrentCulture.NumberFormat.NumberDecimalSeparator))
            strComas = strValor.Substring(strValor.LastIndexOf(Application.CurrentCulture.NumberFormat.NumberDecimalSeparator) + 1)
        Else
            strAux = strValor
        End If

        If strAux.Substring(0, 1) = Application.CurrentCulture.NumberFormat.NegativeSign Then
            bolMenos = True
            strAux = strAux.Substring(1)
        End If

        strPuntos = strAux
        strAux = ""
        While strPuntos.Length > 3
            strAux = Application.CurrentCulture.NumberFormat.NumberGroupSeparator + strPuntos.Substring(strPuntos.Length - 3, 3) + strAux
            strPuntos = strPuntos.Substring(0, strPuntos.Length - 3)
        End While
        If intNumDecimales > 0 Then
            If strValor.Contains(Application.CurrentCulture.NumberFormat.PercentDecimalSeparator) Then
                strComas = Application.CurrentCulture.NumberFormat.PercentDecimalSeparator + strValor.Substring(strValor.LastIndexOf(Application.CurrentCulture.NumberFormat.PercentDecimalSeparator) + 1)
                If strComas.Length > intNumDecimales Then
                    strComas = strComas.Substring(0, intNumDecimales + 1)

                End If
            End If
        End If
        strAux = strPuntos + strAux + strComas


        Return strAux
    End Function


    Private Sub TextBox1_KeyUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyUp
        TextBox1.Text = Puntos(TextBox1.Text, 2)
        TextBox1.Select(TextBox1.TextLength, 0)
    End Sub

Para evitar, que metan en la caja de texto mas de un caracter decimal:

c#

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (textBox1.Text.Contains(Application.CurrentCulture.NumberFormat.NumberDecimalSeparator) && (e.KeyChar == Application.CurrentCulture.NumberFormat.NumberDecimalSeparator))
                e.Handled = true;
            else
                e.Handled = false;
        }


VB


 Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
        If TextBox1.Text.Contains(Application.CurrentCulture.NumberFormat.PercentDecimalSeparator) And (e.KeyChar = Application.CurrentCulture.NumberFormat.PercentDecimalSeparator) Then
            e.Handled = True
        Else
            e.Handled = False
        End If
    End Sub




sábado, 16 de enero de 2010

Pequeños truquillos(1)

Os dejo una lista de truquillos de código que más de una vez nos salvan de apuros:
CONOCER LA RUTA DIRECTORIO ESPECIAL:
Para conocer la ruta de un directorio especial dentro del equipo (Mis documentos, Mis Imágenes)….
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)

La enumeración SpecialFolder del Namespace nos indica algunos directorios especiales y con la función GetFolderPath obtenemos la ruta completa

CONOCER EL DIRECTORIO EN EL QUE ESTAMOS TRABAJANDO:

Environment.CurrentDirectory

CONOCER LA RUTA DEL FICHERO EXE DE NUESTRA APLICACIÓN

Application.StartUpPath

OBTENER UN LISTADO DE LAS UNIDADES DE NUESTRO EQUIPO (1):
For Each Str As String In Environment.GetLogicalDrives()
            MsgBox(Str)
        Next
OBTENER UN LISTADO DE LAS UNIDADES DE NUESTRO EQUIPO (2):

Versión con expresión Lambda y lista…

Environment.GetLogicalDrives().ToList.ForEach(Function(str) Msgbox(str))

OBTENER UN LISTADO DE LOS PARAMETROS RECIBIDOS EN LA LINEA DE COMANDOS:

Environment.GetCommandLineArgs()

DETERMINAR SI UN FICHERO EXISTE
 My.Computer.FileSystem.FileExists("RUTAFICHERO.EXTENSION")

OBTENER EL LISTADO DE FICHEROS DE UN DIRECTORIO:
My.Computer.FileSystem.GetFiles("DIRECTORIO")

DETERMINAR LA INFORMACIÓN DE UN FICHERO:
My.Computer.FileSystem.GetFileInfo("FICHERO")

DETERMINAR LA INFORMACION DE UN DIRECTORIO:
My.Computer.FileSystem.GetDirectoryInfo("DIRECTORIO")

Continuará…

domingo, 10 de enero de 2010

Rellenar un listview con un DataTable y usar filtros.

Muchas veces se pregunta en los foros formas alternativas al datagridview de visualizar los datos en una aplicación WinForms.
Para ello, he hecho un pequeño proyecto y voy a ir detallanado su funcionamiento:
1ª Parte: Definición del Listview
Para que el Listview tenga un aspecto más adecuado a nuestras pretensiones vamos a cambiar 2 de sus propiedades:
-          View: Es la forma de represantar los datos. Vamos a establecer que sea del tipo “Details”.
-          GridLines: Cuando se encuentra en el modo “Details” se pueden ver o no las líneas. Vamos a establecer el valor a “True”
2ª Parte: Obtener los datos
Como en todos los controles de representación de datos necesitamos los datos que vamos a visualizar. Para ello, he creado una pequeña base de datos Access con una tabla Movies, con los siguientes campos:
1 ID
2 Titulo
3 Director
4 Descripcion
Podeis usar vuestras propias clases para obtener los datos, yo lo he hecho con un DataAdapter llenando una tabla.
  Function BuscarDatos(ByRef dt As DataTable, Optional ByVal filtro As String = "") As Boolean
        Dim bolResultado As Boolean = True

        Dim cmd As OleDbCommand
        Try
            If dt Is Nothing Then dt = New DataTable

            Using con As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\movies.accdb;Persist Security Info=False;")
                cmd = New OleDbCommand("SELECT ID,TITULO,DIRECTOR,DESCRIPCION FROM MOVIES WHERE TITULO LIKE @FILTRO OR " & _
                                     " DIRECTOR LIKE @FILTRO OR DESCRIPCION LIKE @FILTRO", con)
                cmd.Parameters.AddWithValue("@FILTRO", "%" & filtro & "%")
                Using DA As New OleDbDataAdapter(cmd)
                    DA.Fill(dt)
                End Using
            End Using
        Catch ex As Exception
            bolResultado = False
        End Try
        Return bolResultado
    End Function
La función recibe como parámetros:
Un datatable para guardar los datos. Lo recibe por referencia.
Y de forma opcional un filtro.
La función si se ejecuta correctamente nos va a devolver “True”, en otro caso nos devolverá false.
3ª Rellenar El Listview
Una vez que tenemos nuestro Datatable relleno, es hora de mostrar los datos en el ListView, para ello, haremos uso de la siguiente función:
Function RellenarListview(ByVal dt As DataTable) As Boolean
        Dim bolResultado As Boolean = True
        Dim lstElemento As ListViewItem
        Try
            Me.lvwDatos.Items.Clear()
            Me.lvwDatos.Columns.Clear()
            For Each col As DataColumn In dt.Columns
                lvwDatos.Columns.Add(col.ColumnName, col.ColumnName)
            Next
            For Each row As DataRow In dt.Rows
                lstElemento = New ListViewItem
                lstElemento.Text = row(0).ToString()
                For intcontador As Integer = 1 To dt.Columns.Count - 1
                    lstElemento.SubItems.Add(row(intcontador).ToString())
                Next
                lvwDatos.Items.Add(lstElemento)
            Next
            Me.lvwDatos.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize)
        Catch ex As Exception
            bolResultado = False
        End Try
        Return bolResultado
    End Function
4ª Filtrar los datos.
En el ejemplo, al ser una base de datos realmente pequeña, el filtrado de datos lo hago directamente con respecto de la base de datos, pero no es la única forma de hacerlo, también lo podemos hacer a través de filtros en el propio datatable a través de la función “Select”.
En este ejemplo, he creado el botón “Filtrar” y el checkBox “Filtrado Automatico”. Ambas funcionalidades hacen que se filtre el contenido del listview, pero en distintos lugares.
El botón Filtrar, evidentemente, provoca el filtrado en el evento Click del botón, sin embargo cuando tenemos marcado el checkBox de “Filtrado automatico”, se filtran los datos según vayamos escribiendo en la caja de texto.

Espero que os haya gustado el articulo.
PD: El ejemplo está hecho en VB 2010 Beta 2, pero es completamente aplicable a vb2008 y vb2005.
PD2: Si necesitais el ejemplo en c# no dudéis en pedírmelo.