Evento NotInList en Access 2007
En Access 2007, el evento NotInList puede funcionar exactamente igual que en versiones anteriores, pero dos nuevas propiedades de los cuadros combinados y listas, Permitir ediciones de la lista de valores y Formulario de edición de la lista, pueden hacer innecesario escribir una sola línea de código para este evento. Fue empezar a escribir estas líneas antes de las vacaciones y verme explicando en algún foro a algún no tan principiante cómo se utiliza NotInList, así que no está de más empezar repasando la manera más canónica de usarlo, pues aún hay gente que no lo entiende y se complica haciendo cosas raras; luego contaremos como, modificando un par de propiedades, en Access 2007 puede ser innecesario.
El evento NotInlist en cualquier versión de Access
Manejar el evento NotInList suele resultar complicado a los principiantes. A pesar de su simplicidad aparente, se manejan algunos conceptos con los que posiblemente no estén familiarizados.
Aunque esté claramente explicado en la ayuda, suele obviarse que el evento NotInList cuenta con dos parámetros con un cometido muy específico: NewData nos proporciona el valor que hemos introducido y que no está en la lista y Response espera que le demos un valor de entre una serie de opciones (acDataErrDisplay , acDataErrContinue o acDataErrAdded) para que la aplicación actúe en consecuencia, mostrando mensaje de error o no o aceptando el nuevo valor y haciendo un requery del combo.
A veces no basta con meter un dato directamente a una tabla, sino que es necesario abrir un formulario para añadir ese y otros datos. La cuestión aquí es cómo esperar a que se introduzca, o no, el nuevo dato y luego darle el valor apropiado al parámetro Response. Es fácil si se tienen las claves:
Si al abrir un formulario DoCmd.Openform utilizamos la constante acDialog en el parámetro WindowMode, éste se abrirá en modo diálogo, de manera que cualquier otro código se detiene hasta que cerremos el formulario.
DoCmd.OpenForm "Detalles de clientes", , , , acFormAdd, acDialog
Ahora, el problema está en pasar información entre el formulario que está abierto y el que ha detenido el código hasta que se cierre el otro. A mí me gusta dimensionar una variable como pública en la sección de declaraciones del formulario que contiene el cuadro combinado. Al declararla como pública será accesible desde cualquier lugar de la aplicación, como si fuera una propiedad del formulario, con la ventaja de que morirá con el formulario. Podemos asignarle un valor desde el formulario abierto en modo diálogo y luego comprobarlo al cerrar éste.
El código completo en el formulario del evento NotInList sería el siguiente:
Option Compare Database
Option ExplicitPublic Respuesta As Integer
Private Sub Id_de_cliente_NotInList(NewData As String, Response As Integer)
DoCmd.OpenForm "Detalles de clientes", , , , acFormAdd, acDialog, NewData
Response = Me.Respuesta
End Sub
Y, en el formulario diálogo, bastaría con una cosa así:
Private Sub cmdAceptar_Click()
Forms!Pedidos.Respuesta = acDataErrAdded
End SubPrivate Sub cmdCancelar_Click()
Forms!Pedidos.Respuesta = acDataErrContinue
End Sub
Es decir, al Aceptar o Cancelar, damos a la variable pública Respuesta del primer formulario el valor que luego tomará Response.
Normalmente, querremos que en el formulario de edición ya se haya insertado el nuevo valor introducido en la lista en su cuadro de texto correspondiente. Para eso, en el último parámetro de la instrucción Docmd.OpenForm, OpenArgs, he pasado el valor de NewData:
DoCmd.OpenForm "Detalles de clientes", , , , acFormAdd, acDialog, NewData
En el formulario para añadir el nuevo dato comprobamos si estamos en un nuevo registro y si hemos pasado algún valor en OpenArgs, en cuyo caso, nos posicionamos en el control correspondiente con SetFocus y ponemos en la propiedad Text el valor que hemos recibido en OpenArgs.
Option Compare Database
Option Explicit
Private Sub Form_Load()
If Me.NewRecord And Nz(Me.OpenArgs, "") <> "" Then
Me.Apellidos.SetFocus
Me.Apellidos.Text = Me.OpenArgs
End If
End Sub
El Evento NotInlist en Access 2007
En Access 2007, dos nuevas propiedades de los cuadros combinados y listas, "Permitir ediciones de la lista de valores" y "Formulario de edición de la lista", pueden suplir al evento NotInlist.
Propiedad Permitir ediciones de la lista de valores
Si el Tipo de origen de la fila es Lista de valores y el cuadro combinado o lista tiene una sola columna, si establecemos el valor de la propiedad Permitir ediciones de la lista de valores a Sí, podremos modificar sus valores en tiempo de ejecución. Tenemos dos posibilidades:
Editar directamente la lista
Al desplegar un cuadro combinado o lista que tenga Permitir ediciones de la lista de valores, se muestra al final de la lista un icono flotante.
Si pulsamos sobre el icono, se despliega un formulario para editar los valores de la lista, incluso podemos editar el valor predeterminado.
Al no estar en lista
Funciona de la misma manera que el evento NotInList, de hecho, en primer lugar se dispararía ese evento. Es decir, si la propiedad Limitar a Lista es Sí e introducimos en ella un valor inexistente, Access 2007 nos informará de que no existe el valor y nos preguntará si deseamos modifcar los elementos de la lista, en cuyo caso nos abriría el mismo formulario para editar valores que en el caso anterior.
Ambas posibilidades sólo funcionan si la lista o cuadro combinado sólo tiene una columna. Si tiene más de una columna, tendríamos que recurrir a los mismos métodos de versiones anteriores.
Propiedad Formulario de edición de la lista
La propiedad Formulario de edición de la lista indica el nombre del formulario que queremos usar para editar los valores de un cuadro combinado o lista cuando cuando la propiedad "Tipo de origen de la fila" es Tabla o Consulta.
Lo mismo que veíamos cuando el tipo de origen de la fila era "Lista de valores", podemos editar los valores en tiempo de ejecución, bien pulsando directamente sobre el icono flotante al final de la lista desplegada, bien al introducir un valor que no existe; la diferencia es que el formulario de edición será uno que nosotros hayamos creado para editar la tabla subyacente al combo o lista.
Nuestro formulario se abrirá en modo diálogo (no necesariamente emergente) deteniendo la ejecución del código de los demás formularios. Al cerrarse, si se han modificado los datos, se actualizará el origen de datos del combo o lista. y si el texto que habíamos introducido coincide con un nuevo valor, se dará por válido y no se producirá error. O sea, más o menos lo que nosotros habríamos hecho editando el evento NotInList.
Añadiendo un poco de código
Pero este formulario se comportará exactamente igual si hemos pulsado el icono flotante para editarlo que si se ha abierto al no estar en la lista, es decir, se abre en modo edición en el primer registro. Seguramente querremos que se comporte como hemos hecho mediante código en versiones anteriores, o sea, que vaya directamente a un registro nuevo y que posicione en el cuadro de texto correspondiente el valor que hemos introducido en la lista ¿Cómo conseguimos esto? Tendremos que usar un mínimo de código.
Si en el formulario de edición de la lista ponemos el siguiente código
Private Sub Form_Load()
Debug.Print Me.OpenArgs
End Sub
Al no estar en lista, en la venta de inmediato del editor de VBA nos encontraremos algo así:
[Detalles de pedidos de compra]![Supplier ID]=Ramirez
Es decir, que al abrirse el formulario el formulario de edición de la lista, sin necesidas de ninguna intervención por nuestra parte, Access 2007 ha pasado un argumento OpenArgs con el nombre del formulario y el del cuadro combinado o de lista y el valor que hemos dado a éste. Podemos utilizar OpenArgs para, si existe, ir a un registro nuevo y rellenar el cuadro de texto correspondiente:
Private Sub Form_Load()
Dim v As Variant
If Nz(Me.OpenArgs, "") <> "" Then
If InStr(Me.OpenArgs, "=") <> 0 Then
v = Split(Me.OpenArgs, "=")
DoCmd.GoToRecord , , acNewRec
Me.Apellidos.SetFocus
Me.Apellidos.Text = v(1)
End If
End If
End Sub
Pero ¿Qué pasa con el evento NotInlist en Access 2007?
Podemos usar el evento NotInList junto con la propiedad Formulario de edición de la lista. En primer lugar se disparará el evento y luego, dependiendo del valor que en éste demos a Response, se abrirá automáticamente, o no, el formulario de edición de la lista.
6 Responsesso far
Lo estaba esperando como agua de mayo, este no tan principiante 😉 descubrió, en su momento, la cantidad de código que me podía haber ahorrado usando correctamente el evento NotInList. Como siempre, felicitarte por el artículo, me parece muy educativo.
Se echaba de menos un articulito 🙂 Y si es tan majo como este, la mar de bien.
Estimado amigo, siguiendo tus indicaciones para aplicar el evento NotInList a mi flamante nueva accdb 2007 he encontrado, en las últimas líneas de código del artículo un detalle que podría llevar a error. Te explico, a la hora de llamar al formulario de edición de valores lo puedes hacer de dos formas, como bien explicas, una es escribiendo el nuevo valor y dejar que Access, previa pregunta, nos lleve al formulario de edición pasándole en el OpenArgs el nombre del formulario mas el valor escrito, hasta aquí tu código funciona correctamente, el problema es cuando lo hacemos usando el segundo método osea, desplegamos el combo y pulsamos sobre el botoncito que aparece al final de la lista, sin que hallamos escrito ningún valor nuevo, en ese caso también nos llama al formulario de edición y también pasa en el OpenArgs el nombre del formulario pero solo hasta el símbolo «=» , a través de «Split» dividimos la cadena y en la variable V(1) nos queda «» puesto que después del símbolo igual no hay nada y, eso mismo es lo que se aplica al campo Apellidos. Esto puede crear un problema, puesto que estamos dando de alta directamente un nuevo registro con ese campo en blanco y si cierras el formulario sin hacer ningún cambio mas, te quedaría un registro en blanco o, lo que es mas normal, que «Apellido» sea clave primaria y al cerrar nos de el mensaje de error pues no puede contener valor nulo. Con tal de evitarlo te envío una modificación a modo de sugerencia a ver que tal:
Private Sub Form_Load()
Dim v As Variant
If Nz(Me.OpenArgs, «») <> «» Then
v = Split(Me.OpenArgs, «=»)
If v(1) <> «» Then
DoCmd.GoToRecord , , acNewRec
Me.Apellido.SetFocus
Me.Apellido.Text = v(1)
End If
End If
End Sub
hey como hago para restringirle que un usuario no inserte datos en un combo box sino que solo el administrador lo haga
Y como llamo otro campo adicional en este evento?, conseguí un códico que me permite llenar los dos primeros campos, pero mi tabla tiene 3 campos. Como haga para que tambien me traiga el 3er campo para llenarlo?
Buenas Tardes, mi pregunta es solo para conocer como se podría hacer y personalizar el mensaje que da Access en este evento. Yo tengo un Formulario que a su vez tiene un subformulario en donde el usuario registra la información eligiendo desde una lista, sin embargo, puede adicionar elementos a esta lista si no están contemplados. Al programar el evento NotInList pasa los argumentos al formulario que registra el nuevo dato, pero al devolver la respuesta al subformulario, me dice que no está abierto y genera error. (No pasa si se hace con la opción de 2007).
Muchas gracias por su ayuda.