domingo, 27 de abril de 2014

Funciones de texto de Access que podemos usar en consultas, como funcionan y con ejemplos (I)

Recientemente me llamo un amigo todo preocupado a ver si podía ayudarle con una base de datos de Access que heredó y menuda herencia envenenada… una chapuza en todos los sentidos. Pero era lo que había y había que lograr generar una serie de informes para ya (realmente ya tenía que haber entregado el trabajo para cuando me llamó). Lo que me encontré es algo similar a esta captura de una hoja de Excel sacada de Google, pero en Access:
d02
Un montón de datos en un solo campo, en donde había desde nombre y apellidos, pasando por direcciones, un montón de trozos de texto estilo “(B)”, “(NR)”… teléfonos, DNI, varios SI o NO, etc… Todo en un solo campo. Aunque todo tenía una estructura lógica y común a todos los campos (daba la impresión de una importación mal hecha, que en lugar de importar a varios campos, pues todo junto y seguramente fuera así).
Si los distintos valores estuvieran separados por una coma “,”, punto y coma “;”, etc o tuviesen las distintas partes tamaño fijo, pues todo sería extremadamente fácil… Pero aun así, sabiendo usar las funciones de Access y especialmente haciéndolas trabajar juntas, pues es algo que se puede hacer en poco tiempo. Aunque la idea y casi con idénticas funciones también podemos hacerlo en Excel.
Y de eso va este post, una introducción a las funciones agregadas que nos pueden sacar de mas de un apuro cuando nos encontramos con casos como este, pero en lugar de enumerar las distintas funciones útiles y listo, pues en este artículo mencionaré 5 de las más útiles y de más apuros pueden sacarnos, y con ellas mostrar un ejemplo ilustrativo, ya que si no ves lo que se puede hacer con ellas, pues de nada sirven conocer que existen.
Para empezar, si alguno quiere seguir el ejemplo o probar que funciona lo comentado, pues puede descargar los datos de ejemplo que voy a usar, aquí el archivo en formato Access 2007:
El archivo de Access de Ejemplo viene con una sola tabla (USUARIOS), la cual tiene una sola columna (APELLIDOS), tal que así:
a01
Aunque es más sencillo el contenido que la captura primera, para empezar nos servirá para presentar algunas de las funciones más útiles y que servirán igualmente para el primer caso, simplemente complicando más. Además este tutoría pretende ser educativo, por un lado mostrando posibilidades vía ejemplos.
Lo que haremos será:
  • Separar nombre y Apellidos
  • Extraer esa B que aparece al final de algunos registros y en un nuevo campo especificar si estaba presente o no.
Voy  a presuponer que todos saben hacer crear una consulta.
Para hacerlo recurriremos a varias funciones, que iremos introduciendo paulatinamente, entre ellas:
  • Der(cadena;tamaño)
  • Izq(cadena;tamaño)
  • Longitud(cadena)
  • EnCad(inicio;cadena1;cadena2;comparar)
  • Siinm(condicion;siVerdad;siNO)
Y después haremos lo propuesto combinando las distintas funciones. Pero lo mejor es verlo en la práctica… y muy importante, en la parte de cadena siempre podemos usar otro campo de la consulta, sea este un campo de una tabla o un campo calculado… pero importante, para poner un campo, siempre se pone el nombre del campo entre corchetes ([]), por ejemplo: [APELLIDOS].
SiInm no es una función de texto, pero muy útil cuando combinamos con las funciones de texto. En casi todos los sitios la vereis como SiInm, pero cuidado no hay ninguna “L”, que muchos piensan que la segunda “i” es confundida con una “L” y después dicen que no les funciona, es por la funte de texto, que en muchas una “L” minúscula se confunde con una “i” mayúscula.

Ejemplo de uso de las funciones:

Cadena: “ALBALADEJO COMPANY, ABEL
Der([cadena];4): “ABEL
Der([cadena];6): “, ABEL
Izq([cadeba];4): “ALBA
Izq([cadeba];6): “ALBALA
Longitud([cadena]): 24
EnCad(1;[cadena];”,”): 19
EnCad(1;[cadena];”c”;0): 0
EnCad(1;[cadena];”c”;1): 12
EnCad(1;[cadena];”c”): 12
SiInm(EnCad(1;[APELLIDOS];"CO")>0;"SI";"NO"): SI
SiInm(EnCad(1;[APELLIDOS];"H")>0;"SI";"NO"): NO

Explicación:

La función Der devuelve los caracteres que hay a la derecha de la cadena, concretamente la cantidad que hayamos indicado en tamaño, si la cadena tiene menos caracteres que lo pedido, pues nos devuelve la cadena completa y nada más (no rellena).
La función Izq igual que Der, pero empieza por la Izquierda de la cadena a coger los caracteres.
La función Longitud nos devuelve la cantidad de caracteres que tiene la cadena.
La función EnCad comprueba si dentro de una cadena (cadena1) hay otra cadena (cadena2) y si la hay, devuelve en que posición empieza a aparecer cadena2 en cadena1… siempre busca a partir de una posición inicial que hay que indicar, si queremos que empiece a comparar por el principio, pues hay que poner 1 como posición de inicio. No hace falta especificar el campo comparar, el cual sirve para especificar la forma de la búsqueda, cuyas opciones principales son: 0 para búsqueda binaria y 1 para búsqueda textual, que en lenguaje llano, pues 0 es cuando queremos que distinga mayúsculas y minúsculas y 1 cuando no, si no se especifica nada, se toma como una búsqueda textual (no distingue mayúsculas y minúsculas). Hay un par de opciones más en el campo búsqueda, como –1 y 2 (esta solo en Access 2007 y posteriores), pero por ahora olvidaos de ellas. Cuando no encuentra coincidencia o cadena2 es de mayor tamaño que cadena1, devuelve 0.
La función Siinm nos permite comprobar si se cumple una condición, y dependiendo de si se cumple o no, pues devolverá lo establecido en siVerdadero o en SiNO. Además podemos poner expresiones en las partes Verdadera y falsa, etc, que es lo que nos da mucha flexibilidad.
Bien, hasta aquí es donde llegan muchísimos tutoriales, la mayoría muchísimo mejores que este. Pero la potencia de estas funciones no es usarlas separadamente, sino combinándolas, punto en donde en pocos tutoriales entran y si lo hacen, normalmente es con las combinaciones más simples.

Empezando que es gerundio:

Pues empezaremos por separar apellidos del resto, que es lo más fácil.
Si nos fijamos hay una “,” entre los apellidos (que van primero) y el nombre. Eso nos da que parte son apellidos. Que necesitamos: la función Izq que nos devuelve la parte de una cadena del tamaño que le solicitemos empezando por la izquierda, la función EnCad que nos da la posición (si está) de otra cadena dentro de una cadena y en este caso de la coma. El campo calculado acaba quedando así:
ApellidosSolo: Izq([APELLIDOS];EnCad(1;[APELLIDOS];",")-1)
a02
Donde ApellidoSolo es el nombre que le damos al campo calculado, una captura de la consulta en funcionamiento siempre ayuda:
a03
a04
Ahora vamos al final, pero solo para ir aumentando la complejidad de las consultas. Lo que vamos a hacer, es en un nuevo campo (BAJA), pues rellenarlo de SI si hay una B y NO en caso contrario. Para ello usamos SiInn a la que pasaremos como condición si hay la subcadena buscada usando EnCad, la cual da un número positivo si la hay y 0 si no, y entonces completamos la condición viendo si ese resultado es mayor de 0. Además sirve como un paso intermedio con la siguiente parte. La formula y el resultado serían:
Baja: SiInm(EnCad(1;[APELLIDOS];"(B)";1)>0;"SI";"NO")
a05
a06
Es importante que la condición esté bien formada, lo que viene significando que la expresión de condición o es un campo SI/NO o BOOLEANO, o es una inecuación (y por tanto aparece una igualdad o un < o >).
Solo nos falta obtener el nombre y es lo que haremos ahora, pero primero sin tener en cuenta lo del paso anterior y después teniéndolo. El motivo de proceder así, es que este artículo pretende ser ilustrativo y la forma de que eso ocurra, es ir mostrando ejemplos que vayan incrementando su complejidad.
En si, esto es muy similar al se sacar los apellidos, la diferencia es que antes con saber el punto por donde debíamos coger era directo y directamente nos servía para saber cuando coger, ahora el punto se calcula igual, pero para saber cuantos caracteres debemos coger, pues hay que saber la longitud de la cadena y con ese dato y el punto a partir del cual queremos, pues calcular cuantos caracteres coger. Además, como en el caso anterior, hay que sacar 1, porque en el anterior te daba la cifra de la primera posición de la cadena buscada y ahora nos sobra un espacio, ya que después de la coma siempre viene un espacio:
Nombre1: Der([APELLIDOS];Longitud([APELLIDOS])-EnCad(1;[APELLIDOS];",")-1)
a07
a08
Ahora será teniendo en cuenta todo, que al final no aporta nada nuevo, simplemente es usando las funciones que tenemos, creando expresiones más complejas para que hagan lo que necesitamos. Y además, pues en este caso, en la función SiInm pues en la parte de VERDADERO y FALSO, pues en lugar de un valor, pues hay otra expresión.
Ya que ahora queremos lo mismo que antes, pero sin las B, cuando las haya:
Nombre: SiInm(EnCad(1;[APELLIDOS];"(B)")>0;Izq(Der([APELLIDOS];Longitud([APELLIDOS])-EnCad(1;[APELLIDOS];",")-1);Longitud(Der([APELLIDOS];Longitud([APELLIDOS])-EnCad(1;[APELLIDOS];",")-1))-4);Der([APELLIDOS];Longitud([APELLIDOS])-EnCad(1;[APELLIDOS];",")-1))
a09
a10
Esta función parece muy larga y compleja, pero larga si que es, pero no tiene ningún misterio, simplemente hemos: a partir de un texto, extraer la parte que nos interesa usando 5 funciones, una que nos permite coger una parte de un texto por la derecha, otra idem pero por la izquierda, otra que nos da la longitud de un texto, otra que nos permite saber si dentro de ese texto hay un fragmento que nosotros le indiquemos, y si lo hay nos da donde empieza… y por último una que, dependiendo de una condición lógica, pues devolverá una opción u otra.
Y en el ejemplo ni siquiera se ven todas las posibilidades de estas funciones, por ejemplo, en EnCad, podemos trabajar con la posición inicial en donde empieza a buscar, y por ejemplo poner ahí otra EnCad que busca otro fragmento y así buscamos la primera aparición (si la hay) desde ese fragmento, etc.
Pero creo que este pequeño artículo ya da una idea de las posibilidades que tenemos a nuestro alcance, aunque en artículos posteriores se mostrarán otras funciones, como la función Medio() que también podríamos haber usado en este artículo para hacer el ejemplo, entre otras (Recortar, RecortarIzq, RecortarDer, DBusq, Espacio…). Aunque con estas por hoy creo que ya dan una idea de las posibilidades y de lo importante que es conocerlas. Para finalizar solo una captura del ejemplo echo todo junto:
a11
Hasta el próximo artículo y espero que no tardar tanto en hacer el siguiente.

1 comentario:

  1. Gracias por tu aporte, pero que hacer cuando quiero separar solo un nombre, del campo nombre, utilice xpr01: Izq([nombre];EnCad(1;[nombre];"")), funciona cuando el campo tiene un solo nombre pero cuando tinee dos no. ejemplo: Jorge, Luis, Carlos aleberto. que devuelva jorge, luis y carlos. gracias

    ResponderEliminar