|
| |
 |
 |
 |
 |
 |
 |
 |
 |
|
Introducción:
Utilidad de BuildCriteria |
 |
 |
|
Construir adecuadamente las expresiones de filtro o
de búsqueda es una tarea que se le atraganta a más de uno.
Las
cadenas de texto entre comillas,
las fechas entre almohadillas y
en formato americano, los
decimales con punto en vez de
coma... Sin embargo, cuando
diseñamos una consulta en vista
diseño es mucho más sencillo;
parece que Access entiende
nuestro idioma y le podemos
pasar fechas sin formatear,
cadenas de texto sin comillas,
incluso le podemos hablar en
español (Entre... y...) o en
inglés (Between... and ...) que
lo interpreta correctamente. Si
luego leemos el código SQL
generado, vemos que Access se ha
ocupado de formatear, delimitar
y traducir nuestras expresiones
para que funcionen
correctamente.
Lo
mismo ocurre si ponemos
parámetros a nuestra consulta y
se los asignamos con código,
como explica Juan M. Afán de
Ribera en su artículo
Consulta con parámetros.
Pues
bien, ese mismo mecanismo
interno para construir
correctamente las cadenas de
criterio está disponible, desde
las primeras versiones de
Access, utilizando la función
BuildCriteria. Porqué
entonces nos rompemos la cabeza
montando nuestras cadenas "a
mano" es un misterio al que la
única explicación que encuentro
es que aparentemente funciona
mal con campos de texto. Recalco
lo de aparentemente porque
volveré sobre ello más adelante.
La
ayuda de Access cuenta de
BuildCritera cosas como: |
|
Comentarios
El método BuildCriteria
devuelve una cadena de caracteres.
El método BuildCriteria
permite construir fácilmente criterios para un filtro que se
base en las entradas del usuario. Analiza el argumento
expresión de la misma forma que si la expresión hubiera
sido analizada si hubiera sido introducida en el modo
Cuadrícula de diseño de la consulta, Filtro por formulario o
Filtro de servidor por formulario.
Por ejemplo, un usuario que crea una
consulta en una tabla Pedidos puede restringir la hoja de
respuestas dinámica a los pedidos que se hayan hecho después
del 1 de Enero, 1995, estableciendo los criterios en un
campo FechaPedido. El usuario podría introducir una
expresión como la siguiente en la fila
Criterios bajo el campo FechaPedido:
>1-1-95
Microsoft Access analiza automáticamente
esta expresión y devuelve la siguiente expresión:
>#1/1/95#
El método BuildCriteria
ofrece el mismo análisis desde el código Visual Basic. Por
ejemplo, para devolver la cadena anterior correctamente
analizada, se pueden suministrar los siguientes argumentos
al método BuildCriteria:
Dim strCriteria As String
strCriteria = BuildCriteria("OrderDate", dbDate, ">1-1-95")
Dado que es necesario suministrar
criterios para la propiedad Filtro (Filter)
en un formulario con la sintaxis analizada correctamente,
puede utilizar el método BuildCriteria
para construir una cadena analizada correctamente:
Se puede utilizar el método
BuildCriteria para construir una cadena
con criterios múltiples si esos criterios se refieren al
mismo campo. Por ejemplo, puede utilizar el método
BuildCriteria con los siguientes
argumentos para construir una cadena con criterios múltiples
que estén relacionados con el campo FechaPedido:
strCriteria = BuildCriteria("OrderDate", dbDate, ">1-1-95 and <5-1-95")
Este ejemplo devuelve la siguiente cadena
de criterios:
FechaPedido>#1/1/95# y FechaPedido<#5/1/95# |
|
|
|
|
 |
 |
|
 |
 |
|
 |
 |
 |
 |
 |
 |
 |
 |
 |
 |
|
BuildCriteria con cadenas
de texto: El aparente fallo |
 |
 |
|
Después de maravillarnos viendo con qué facilidad
BuildCriteria resuelve los habituales problemas con los campos de fecha o
decimales al construir criterio, nos llevamos un gran chasco cuando intentamos
hacer lo mismo con las cadenas de texto problemáticas, las que contienen
comillas o apóstrofes en su interior, incluso si contiene paréntesis se produce
el error.
¿Fallo? Pues no.
BuildCriteria está pensado
para evaluar las expresiones que
el usuario introduce; no sólo
formatea correctamente la
cadena, sino que también es
capaza de evaluar operadores
como =,>, <, Entre.., y..,
o.. o incluso funciones que se
incluyan en la expresión. Esto
en un campo numérico es
sencillo: cualquier carácter que
no sea numérico o el separador
decimal se evalúa, con los
campos de fecha parecido, pero
las cadenas de texto pueden
contener cualquier carácter y
entonces la única forma de
distinguir los operadores es que
nosotros mismos diferenciemos el
texto añadiéndole las comillas,
de lo contrario,
Buildcriteria trata de
interpretarlo de la manera más
sencilla.
Si
pasamos como argumento:
Entre
Pinto y Valdemoro
BulidCriteria lo interpreta como
Between
"Pinto" And "Valdemoro"
Por
tanto, si estamos filtrando, nos
quedarán aquellos registros cuyo
campo filtrado sea mayor o igual
que "Pinto"
y menor o igual que
"Valdemoro".
Si,
por el contrario, lo delimitamos
entre comillas:
"Entre
Pinto y Valdemoro"
BuildCriteria lo interpreta como
=
"Entre Pinto y Valdemoro"
Pero
¿Y, si el primer ejemplo fuera
el contenido de un campo de una
tabla y quisiera encontrar el
registro que contiene
Entre
"Pinto" y "Valdemoro"?
En ese caso, BuildCriteria no es
capaz de resolver las comillas
directamente y tendríamos que
pasárselas nosotros y, como se
trata de comillas dentro de
comillas, tendríamos que
recurrir a montar la cadena con
Chr(34) y se nos acabó la
simplicidad.
Entonces, no nos encontramos
ante un fallo, sino ante que es
imposible interpretar dentro de
una cadena de texto qué es texto
y que son operadores si no le
ponemos delimitadores. Se
contemplan las expresiones más
sencillas o más comunes y, a
partir de ahí, la tarea pasa el
usuario.
Sin
embargo, en muchas ocasiones,
por ejemplo cuando el criterio
de búsqueda lo obtenemos de un
cuadro combinado con
Limitar
a lista = Sí, lo que pretendemos es
que nos monten correctamente la
cadena de búsqueda, arreglando
comillas y apóstrofes, y nada
más; no necesitamos ningún
operador distinto de
=. ¿Lo
puede hacer BuildCriteria?
Directamente, no, pero podemos
hacernos una función, que
llamaremos ConstruyeCriterio
y que lo que hace es preparar el
argumento que pasamos a
BuildCriteria para que funcione
correctamente, y, como eso
supone cierta pérdida de
funcionalidad por otro lado, le
añadimos un par de parámetros
para decidir si usamos
BuildCriteria sin más, con su
funcionalidad original, o si la
arreglamos para que monte las
cadenas complicadas.
|
|
|
|
 |
 |
|
 |
 |
|
 |
 |
 |
 |
 |
 |
 |
 |
 |
|
Nuestra función
ConstruyeCriterio() |
 |
 |
|
He elaborado una función muy sencilla,
ContruyeCriterio() que lo que hace es llamar a BuildCriteria, pero
con algunos arreglos:
-
Utiliza una enumeración
DataTypeEnum, en
vez de un entero como
BuildCriteria en el
parámetro
FieldType.
Curiosamente,
BuildCriteria no lo usa
y, sin embargo los valores
que admite como válidos son
precisamente esos. Supongo
que será que es así por
tratarse de una función muy
antigua.
'--------------------------------------------------------------------------------
' Procedure : ConstruyeCriterio
' DateTime : 22/10/06
' Author : José Bengoechea Ibaceta (Chea)
' Purpose : Llamar a la función BuidCriteria() tratando previamente la expresión
' que le pasamos si el campo es de texto y el usuario lo ha decidido
' así.
' En los campos de texto, BuildCriteria puede interpretar ciertos caracteres
' como parte de una expresión y no del literal que se busca, por lo que puede
' ser necesario que le demos una tratamiento previo a esa cadena de texto antes
' de pasarla como argumento. Si vamos a utilizar como criterio texto que incluye
' comillas simples o dobles o paréntesis, debemos tratar previamente ese texto
' añadiéndole comillas, sin embargo, si no lo necesitamos, es preferible no
' añadir esas comillas pues con ellas BuildCriteria no puede interpretar ciertas
' expresiones que pueden ir dentro de este texto.
'
' Puedes encontrar más explicaciones sobre esta función en http://jbengoechea.com
' Estás autorizado a utilizar este código dentro de una aplicación
' siempre que esta nota de autor permanezca inalterada.
' En el caso de querer publicarlo en una página Web, por favor,
' contactar con el autor en
'
' UA@bengoechea.net
'-------------------------------------------------------------------------------
Public Function ConstruyeCriterio(sCampo As String, tipoDato As DataTypeEnum, _
Expresion As Variant, Optional ProcesarComillas As Boolean = True, Optional _
Operador As String) As String
If Operador <> "" And ProcesarComillas = False Then
MsgBox _
"El parámetro 'Operador' sólo se usar si 'ProcesarComillas' es verdadero"
End If
If (tipoDato = dbText Or tipoDato = dbMemo Or tipoDato = dbChar) And _
ProcesarComillas = True Then
If InStr(Expresion, Chr(34)) = 0 Then
Expresion = Chr(34) & Expresion & Chr(34)
Else
Expresion = Replace(Expresion, Chr(34), Chr(34) & " & chr (34) & " & _
Chr(34))
Expresion = Chr(34) & Expresion & Chr(34)
End If
If Operador <> "" Then
Expresion = Operador & Expresion
End If
End If
ConstruyeCriterio = BuildCriteria(sCampo, tipoDato, Expresion)
End Function
|
|
|
En
consultas o en propiedades de
controles, es decir, en la
interfaz más próxima al usuario,
Access no reconoce las
constantes de las enumeraciones,
por lo que debemos sustituir el
nombre de las constantes por su
valor equivalente. Para buscar
los valores de la enumeración
DataTypeEnum lo más
sencillo es buscar en el
Examinador de Objetos, al que
podemos llegar en el menú
Ver
del editor de VB, pero, por si
acaso, añado aquí los posibles
valores.
Valores para DataTypeEnum
|
dbBoolean |
1 |
dbBinary |
9 |
dbChar |
18 |
|
dbByte |
2 |
dbText |
10 |
dbNumeric |
19 |
|
dbInteger |
3 |
dbLongBinary |
11 |
dbDecimal |
20 |
|
dbLong |
4 |
dbMemo |
12 |
dbFloat |
21 |
|
dbSingle |
6 |
dbGUID |
15 |
dbTime |
22 |
|
dbDouble |
7 |
dbBigInt |
16 |
dbTimeStamp |
23 |
|
dbDate |
8 |
dbVarBinary |
17 |
|
|
Bajarse la aplicación demo
|
|
|
|
 |
|
 |
 |
|
 |
 |
|