none
Utilizar caracter comodin * (asterico) para realizar busquedas RRS feed

  • Pregunta

  • Estoy un poco pez en esto, intento realizar busquedas de las filas dentro de un Datatable que contengan lo que el usuario escriba en un textbox, el problema que uso :

    r["Descripcion"].ToString().Contains(palabra);

    pero por ejemplo me gustaria poder usar el * para buscar descripciones que contengan 2 palabras.

    alguna idea ??

    miércoles, 14 de mayo de 2014 15:04

Respuestas

  • En lugar de table.Rows.Add(r), pon table.Rows.Add(r.ItemArray).

    ItemArray extrae los contenidos de r (que viene de la tabla copiada) y devuelve un array de object. Ese array pasa a la sobre carga de Rows.Add que admite un array, y construye una nueva fila con el array. Eso evita el error que dice que r pertenece a otra tabla distinta, ya que la tabla de destino nunca llega a ver "r", sino únicamente el contenido de "r".

    • Marcado como respuesta julian1985 jueves, 15 de mayo de 2014 16:14
    • Desmarcado como respuesta julian1985 jueves, 15 de mayo de 2014 16:24
    • Marcado como respuesta julian1985 viernes, 16 de mayo de 2014 14:48
    jueves, 15 de mayo de 2014 15:47

Todas las respuestas

  • Podrías usar la instrucción Select del DataTable:

    DataRow[] filasEncontradas = MiDataTable.Select("Descripcion LIKE '%palabra1%palabra2%'")

    Observa que en esta instrucción el comodín no es * sino %.

    jueves, 15 de mayo de 2014 6:19
  • Hola.

    Estoy de acuerdo con Alberto.

    Otra alternativa podría ser utilizar expresiones regulares empleando Regexp, aunque posiblemente esta alternativa sea un poco más costosa computacionalmente hablando.

    Un saludo.

    jueves, 15 de mayo de 2014 7:12
  • gracias por las respuestas, pero la idea es que el usuario pueda escribir asteriscos o un caracter comodin en un solo textbox y asi poder realizar el Select como muestra Alberto con 2 o 3 palabras por ejemplo.
    jueves, 15 de mayo de 2014 7:33
  • Bueno, si quieres que el usuario teclee teclee asteriscos, lo que puedes hacer es aplicar un String.Replace para cambiar el asterisco por % en la cadena tecleada por el usuario, y luego pasar el resultado como argumento al Select como indicaba en el ejemplo anterior.

    string cadenaDeBusqueda = TextBox1.Text.Replace("*", "%");

    DataRow[] filasEncontradas = MiDataTable.Select("Descripcion LIKE '" + cadenaDeBusqueda + "'");

    jueves, 15 de mayo de 2014 8:20
  • Muchas gracias por la ayuda Alberto, eso es lo que queria hacer.

    Lo he probado pero ahora me aparecen los campos vacios del datatable que antes me funcionaba te dejo el codigo con la forma antigua comentada a ver si veis algun problema:

    public DataTable buscar(DataTable table, string palabra)
                    {
                        
                        string cadenaDeBusqueda = palabra.Replace("*""%");

    DataRow[] filasEncontradas = table.Select("Descripcion LIKE '" + cadenaDeBusqueda + "'");
                        
                        if(palabra.Length==13) palabra= palabra.Substring(6,6);
                table.Rows.Clear();
                    for(int i=0;i<filasEncontradas.Length;i++)
                    {    
                    DataRow r = table.NewRow();
                     r = filasEncontradas[i];
                     
                
                        //if (r["CodigoArticulo"].ToString().Contains(palabra))  ;
                        //else if (r["Descripcion"].ToString().Contains(palabra))  ;
                        //else {table.Rows.Remove(r);i--;}
                    
                        table.Rows.Add(r);
                        
                 }
                    return table;
                    
                    }

    jueves, 15 de mayo de 2014 10:14
  • Tengo una sospecha sobre cuál puede ser el problema, pero tendrías que verificarlo siguiendo paso a paso la ejecución con el debugger y examinando el DataTable y las filas en cada paso. La cuestión es la siguiente:

    (1) Partimos de un datatable que te llega como argumento y viene cargado con filas.

    (2) Extraemos a partir de ese datatable un array de filas que son las que queremos conservar.

    (3) Se hace un Clear del datatable para borrar las filas.

    (4) Añadimos al datatable que ahora está vacío las filas obtenidas en el paso (2).

    Esto funcionaría bien si las filas extraídas en el paso (2) fueran una copia de las originales. Pero en realidad, el array solo contiene una referencia a las originales. Mi sospecha, y esto es lo que tendrás que verificar, es que el Clear limpia esas filas originales, y por lo tanto también se limpian los contenidos que se ven a través de las referencias del array.

    Si efectivamente se comprueba que el problema es este, un remedio sencillo sería usar el método Copy para construir una copia del DataTable, y hacer el Select sobre esa copia.

    Por cierto, una observación: es superflua la instrucción DataRow r = table.NewRow(), dado que justo en la siguiente línea le asignas un nuevo valor a la r que sustituye al que acabas de construir con esa instrucción.

    jueves, 15 de mayo de 2014 11:04
  • Efectivamente el problema es como lo describes, y la solucion tan sencilla como me comentas :

    "Si efectivamente se comprueba que el problema es este, un remedio sencillo sería usar el método Copy para construir una copia del DataTable, y hacer el Select sobre esa copia."

    Pero he intentado realizarlo de diferentes formas y siempre obtengo el error al ejecutar el .Add(r):

    System.ArgumentException: Esta fila ya pertenece a otra tabla.

    Te dejo el codigo:

    public DataTable buscar(DataTable table, string palabra)
                    {
                        
                        string cadenaDeBusqueda = palabra.Replace("*""%");
                        DataTable table2 = new DataTable();
                        table2 = table.Copy();

    DataRow[] filasEncontradas = table2.Select("Descripcion LIKE '" + cadenaDeBusqueda + "'");
                        
                        if(palabra.Length==13) palabra= palabra.Substring(6,6);
                        table.Clear();
                   foreach(DataRow r in filasEncontradas)
                    {    
                      
                    
                     
                    
                        //if (r["CodigoArticulo"].ToString().Contains(palabra))  ;
                        //else if (r["Descripcion"].ToString().Contains(palabra))  ;
                        //else {table.Rows.Remove(r);i--;}
                        
                        table.Rows.Add(r);
                        
                 }
                    return table;
                    
                    }



    • Editado julian1985 jueves, 15 de mayo de 2014 14:41
    jueves, 15 de mayo de 2014 14:38
  • En lugar de table.Rows.Add(r), pon table.Rows.Add(r.ItemArray).

    ItemArray extrae los contenidos de r (que viene de la tabla copiada) y devuelve un array de object. Ese array pasa a la sobre carga de Rows.Add que admite un array, y construye una nueva fila con el array. Eso evita el error que dice que r pertenece a otra tabla distinta, ya que la tabla de destino nunca llega a ver "r", sino únicamente el contenido de "r".

    • Marcado como respuesta julian1985 jueves, 15 de mayo de 2014 16:14
    • Desmarcado como respuesta julian1985 jueves, 15 de mayo de 2014 16:24
    • Marcado como respuesta julian1985 viernes, 16 de mayo de 2014 14:48
    jueves, 15 de mayo de 2014 15:47
  • Perfecto, eso es lo que no sabia.

    Gracias, eres un crack.

    jueves, 15 de mayo de 2014 16:14
  • Ups me acabo de dar cuenta que el % para el LIKE solo se puede usar al principio o al final o ambas, pero no en mitad de una cadena. por ejemplo: opel%rojo para buscar opel corsa rojo y opel astra rojo.

    Asi la utilidad es muy similar a la del .contains(), de todas formas si se ocurre otra solucion sera bienvenida.

    Imagino que realizando un primer select y despues otro sobre la tabla ya creada, luego me pongo con ello a ver si funciona.
    • Editado julian1985 jueves, 15 de mayo de 2014 16:30
    jueves, 15 de mayo de 2014 16:27