Problema Eliminación de datos Entre Tablas
Me surge un problema que ya no se como voy a resolverlo...
En una BD para criadero de animales tengo dos tablas una con todos los datos de los criadores y en particular dos campos NombreCriador y NºCriador (TablaCriadores) y otra con los animales (TablaAnimales) con todos los datos del animal, bien para no tener que rellenar el nombre del criador en TablaAnimales puse un cuadro combinado para elegir el nombre del criador (cboCriador) origen del control NombreCriador de TablaCriadores donde eliges el nombre y ahora es donde viene el problema, las tablas no están relacionadas entre si pero resulta que al eliminar un criador de la tabla TablaCriadores me borra también el nombre de la TablaAnimales todos los datos del animal quedan igual en la tabla excepto el nombre del criador que se borro pero en el formulario basado en la TablaAnimales no muestra los registros a los que le falta el nombre del criador. He probado a poner el origen del control del cboCriador desde una consulta con el asistente donde te dice al final que puedes guardar un campo en la tabla y le eliges, pero el resultado es el mismo. Mi idea era que aunque yo eliminase un criador de la TablaCriadores en la TablaAnimales no se borraría. ¿Por qué sucede esto?
1 Respuesta
Si el combo lo hiciste con dos columnas (nºCriador y NombreCriador), y el valor que almacena es NºCriador, aunque el que se muestre sea el NombreCriador, realmente no te borra el dato, pero el campo aparece en blanco al no tener un nombre asociado a ese NºCriador. Esto lo puedes comprobar si en el formulario conviertes el cuadro combinado en un cuadro de texto, o en la tabla, le cambias al campo, en la pestaña búsqueda la propiedad Mostrar control a Cuadro de texto.
Una posible solución a este problema, es no realizar un borrado "físico" del registro de TablaCriadores, sino hacer un borrado "lógico" del mismo. Para esto, tendrás que añadir un campo de tipo Si/No a la tabla (yo lo llamo "Eliminado"), y modificar tu botón o código de borrado, para que en vez de borrar el registro, marque ese campo como verdadero.
Luego, tendrás que cambiar el origen del formulario que te muestre los criadores, para que te aparezcan sólo los que no tienen esa casilla marcada (lo puedes hacer con una consulta o una SQL directamente en el origen del formulario)
Además, en tu cuadro combinado (y aquí ya no sé como quieres que funcione tu BD), puedes jugar con el origen del cuadro combinado para que en "modo consulta" te muestre todos los criadores de la tabla, y en "modo edición" o "modo añadir" te muestre sólo los que no están "eliminados"
A ver si esto te ayuda.
Sveinbjorn
Parece una idea que podía probar y ver los resultados.
tengo puesto el botón eliminar que crea access con su macro, entonces me podrías poner como seria por código en el evento al hacer click marcar o activar la casilla de verificación ya que de VBA no se hacer códigos como mucho modificar algunas cosillas.
y por otra parte veo un problema ya que no sabemos lo que el usuario puede hacer en la BD, imaginate que hace un registro criador con su numero de criador que lo tengo en la tabla como indexado sin duplicados puesto que es un numero como el DNI no hay dos iguales y pulsa el botón que hemos cambiado eliminar por desactivar....bien a su vista el registro se elimino, pero no es cierto esta oculto y si decide volver en un futuro registrar el mismo criador en cuanto ponga su numero de criador tendríamos el error de duplicados....
una idea podría ser poner al campo NºCriador como regla de validación "No Es Nulo" para obligar al usuario a que sea el primer campo que tenga que rellenar y generar un código en el evento después de actualizar o al perder el foco que diga "lo pongo en mi idioma je je a ver si lo traduces a VBA":
al perder el foco" comprueba si el numero de Criador existe....si NO existe continua el registro....pero si el numero SI existe lanza un MsgBox y dices "los datos de este criador son recuperables" ¿Quiere recuperarlos? si es SI desactiva la casilla de verificación, y refrescamos el formulario, si es NO lanza un MsgBox "no podrá continuar si no introduce otro numero de Criador"
Que te parece?
Veo que pillaste la idea.
A ver si esta tarde/noche me da tiempo a prepararte una mini. Bd de ejemplo y te la paso y explico lo que tienes que hacer.
si, si lo pille y me parece una solucion muy buena.
para no hacerte perder el tiempo he adelantado terreno y te comento lo que he cambiado:
puse un campo casilla SI/NO llamado "Eliminado" en la tabla criadores.
En el Formulario criadores origen de control Tabla criadores cambie la macro del boton "eliminar" por este codigo que aunque no se casi nada de BVA algunas cosilla si puedo:
en el evento "al hacer Click"
casEliminado.Value = True 'al hacer click marca la casilla de verificacion como verdadero
Me.Requery 'actualiza el formulario
MsgBox "Los Datos fueron eliminados" & Chr(13) & "O.K", , "ELIMINACION DE DATOS" 'lanza un msgBox diciendo que los datos se eliminaron
lo explico para los que no saben, como yo.
El usuario cree que ha borrado el registro al hacer click en "Eliminar" pero no es cierto, solo se ocultaron los datos. asi en el formulario animales siguen perfectamente registrados los datos.
Cree una consulta lamada "FiltroCriadores" con los datos de los criadores y como criterio en el campo "Eliminado" le puse "Falso" asi solo muestra los registros que no tienen la casilla marcada.
ahora creo una macro en el formulario criadores y en el evento "al abrir" o "al Cargar" con la acción "aplicar filtro" con nombre de filtro "FiltroCriadores" y todo perfecto puesto que al hacer click en el boton eliminar marca la casilla y mediante me.Requey actualiza el formulario y la macro lo filtra mostrandome asi solo los registros sin la casilla marcada. todo va perfecto.
solo falta el codigo que te comente anteriormente para los duplicados y la desmarcacion de la casilla si se recuperan los datos.te agradeceria que si realizas el codigo mediante ( ' ) fueras comentandolo asi aprenderemos algo je, je....... gracias
se me olvido comentar que en el cuadro combinado (cboCriador) entre en las propiedades, ficha "Datos" y origen de la fila y entrando en la consulta origen, añado el campo "Eliminado" con criterio "Falso" de esta manera solo muestra los criadores que tienen la casilla desactivada tambien....
Disculpa la tardanza, pero ando con problemas con la gráfica del PC, y llevo media tarde para ponerla a andar...
Veo que lo poco que dices saber lo aplicas bien, y aunque yo no lo he hecho así en el ejemplo que te preparé, la tuya también es una solución igual de válida. Lo único, comentarte una cosa del evento Eliminar:
¿No sería mejor que lanzaras un MsgBox pidiendo confirmar el borrado?
Y supongo que el campo Si/No, lo tienes también en el formulario, pero oculto (es algo que o me quedó claro en tu respuesta)
El código que te mando va comentado linea por linea, o casi, pero te comento aquí los pasos por si lo quieres aplicar a tu BD:
1º/ Añadir el campo Eliminado (de tipo Si/No) a TablaCriadores (ya lo tienes)
2º/ Añadirlo al formulario, pero oculto (imagino que también lo tienes)
3º/ Poner el Formulario Criadores para que no permita añadir registros (Pestaña Datos->Permitir agregar: No)
4º/ Un botón cmdNuevo, para permitir añadir registros.
5º/ El botón eliminar, con el código que ya tienes o el mío (es prácticamente el mismo)
6º/ Yo le cambie el origen al formulario para que muestre los no "eliminados" (tu lo haces mediante un filtro, pero el resultado es el mismo)
7º/ En el campo NºCriador, le programo el evento Antes de actualizar, para que compruebe que el número introducido no esté repetido (te remito al ejemplo para ver el código)
8º/ En el evento Después de actualizar del formulario, le bloqueo añadir registros, para que haya que usar el botón (esto del botón Nuevo (pasos 3,4 y 8), no es estrictamente necesario para que te funcione)
9º/ En el formulario de animales, en el evento Al recibir el enfoque del cuadro combinado del criador, le programo un evento para que se actualice el combo, de esta manera: si es un registro nuevo, que muestre los criadores no eliminados, y si no lo es, que los muestre todos.
http://www.filebig.net/files/mrkqAhAuAV
Si te queda alguna duda, pregunta sin miedo.
bueno Sveinbjorn he adaptado el codigo a mi BD y me da un error en esta linea:
miNumCriador = Me.txtNCN 'le asignas el valor a la variable
el error es: no coinciden los tipos
que despues de dar muchas vueltas creo que se donde esta y es que tu BD el campo en la tabla Criadores NºCriador es de tipo numerico y mi campo es de tipo texto, lo necesito asi puesto que los numeros de criador pueden se como estos: 1S-032, AA-50C, C1-R25 creo que sera que la funcion compara numeros repetidos con tipo numerico pero necesito que lo conpare con tipo texto.....
en tu BD funciona de lujo claro.
otra linea que se podria añadir es cuando haces un nuevo registro e introduces un numero de criador que ya esta registrado y sin marcar como eliminado, perfectamente salta el aviso y he pensado que podria tambien eliminar el registro que se ha activado, ya que sino te metes en un bucle al intentar salir del campo Nºcriador saltando el mensaje continuamente hasta que no cierras el formulario y acces te avisa que no se va a guardar. lo que quiero es que no sea necesario salir del formulario, simplemente ingreso el numero "esta repetido" acces elimina el registro que he activado y puedo continuar.
lo demas esta adaptado sin problema. a ver que te parece....
Haz estos cambios:
1º/ El evento antes de actualizar del campo numero de criador quedaría así (modifico sobre el que te mandé):
'Declaras las variables
Dim miNumCriador As String
Dim resp As Integer
'Si no hay numero, sales sin hacer nada (ya se encarga access de decirte que no puede estar en blanco, pues es clave
'principal, o le pones requerido en Si)
If Nz(Me.NºCriador, "") = "" Then Exit Sub
'Miras si el nº de criador es único, con la función fncNumCriadorUnico (la tienes más abajo)
If fncNumCriadorUnico(Me.NºCriador) = False Then 'Si devuelve falso, es porque ya está en la BD
miNumCriador = Me.NºCriador 'le asignas el valor a la variable
'Ahora compruebas si el NºCriador está "eliminado", mediante la función DLookup
If DLookup("Eliminado", "TablaCriadores", "NºCriador='" & miNumCriador & "'") = True Then
'Avisas de que ya existía un criador con ese número, y preguntas si lo quieres recuperar
resp = MsgBox("Previamente se ha eliminado un criador con este mismo número, y de nombre: " _
& DLookup("Nombre", "TablaCriadores", "NºCriador='" & miNumCriador & "'") & "." & vbCrLf _
& "Si desea volverlo a dar de alta pulse ""Aceptar"", en caso contrario, pulse ""Cancelar"" " _
& "y deberá introducir otro número de colegiado válido", vbInformation + vbOKCancel)
'Si la respuesta es afirmativa
If resp = vbOK Then
Cancel = True 'Cancelas la introducción de datos
DoCmd.SetWarnings False 'desativas los avisos
DoCmd.RunSQL "UPDATE TablaCriadores SET Eliminado=False WHERE NºCriador='" & miNumCriador & "'" 'Des-eliminas el criador
DoCmd.SetWarnings True 'activas los avisos de nuevo
Me.Undo 'Deshaces los cambios del form que pudiera haber
Me.Requery 'Actualizas el formulario
'Y con estas 5, te sitúas en el registro "restaurado"
Dim rst As DAO.Recordset
Set rst = Me.RecordsetClone
rst.FindFirst "NºCriador='" & miNumCriador & "'"
Me.Bookmark = rst.Bookmark
rst.Close
Else
'Si no quieres restaurar el registro, cancelas y queda a la espera de que meta otro NºCriador
Cancel = True
End If
Else 'Si el número no está eliminado, es porque es el de algún criador de alta actualmente
'Avisas de eso
MsgBox "El número de colegiado introducido ya está registrado", vbOKOnly + vbCritical
Cancel = True 'cancelas,
Me.Undo 'Deshaces los cambios
Me.AllowAdditions = False ' Anulas el nuevo registro
End If
End If
Te pongo en negrita las lineas que cambian. Básicamente es cambiar el tipo de declaración de variable (de Long a String), y adaptar los DLookup y el FindFirst. Cuando trabajas con una variable o dato de tipo texto, siempre tienes que encerrarla entre comillas simples ( ' ), por ejemplo,
una variable: "NºCriador='" & miNumCriador & "'"
un dato concreto: "NºCriador='R1-C02'"
Las tres últimas en negrita, es para evitar el bucle que dices. De esta manera, al meter un numero repetido, avisa y cancela el nuevo registro. También se las puedes poner en la parte de que no quiere restaurar el registro eliminado.
Hola de nuevo Sveinbjorn, bueno readacte todo el codigo con algun problemilla que parecen cosas sin importancia pero no funcionaba como debia hasta que lo vi...en esta linea:
If Nz(Me.txtNCN, "") = 0 "" Then Exit Sub (no quite el cero) y en esta
Cancel = True 'Y cancelas, a la espera de que ponga otro NºCriador
Cancel = True 'cancelas,
Me.Undo 'Deshaces los cambios
Me.AllowAdditions = False ' Anulas el nuevo registro
tenia dos Cancel= True (para que sobren je, je)
he puesto todas las cosas en su sitio y he hecho mil pruebas, poniendo una mascara de entrada al NºCriador asi obligo a poner un formato definido y no se escapa ningun duplicado. tambien añadi unas cuantas lineas al codigo (ya era muy facil claro) concretamente aqui:
'Si no quieres restaurar el registro, cancelas y queda a la espera de que meta otro NºCriador
Cancel = True
Me.Undo 'Deshaces los cambios
Me.AllowAdditions = False ' Anulas el nuevo registro
Me.AllowAdditions = True ' permite añadir un nuevo registro
DoCmd.GoToRecord , , acNewRec 'Vas a un registro nuevo
asi tambien si no quieres restaurar el registro "eliminado" eliminamos el numero introducido y lo llevamos a un registro nuevo con el foco en Nº criador
Todo funciona ahora perfectamente.
Te agradezco mucho , mucho la ayuda que me has prestado y te doy las gracias (no es la primera) ya no sabia como iba a solucionar este problema,,,,,Muchas Gracias Sveinbjorn
solo comentar a quien le pueda ayudar esto que se puede construir un formulario tipo administrador y mediante consultas de no coincidentes (en mi caso ya que VBA NO) se pueden eliminar totalmente los registros criadores que no tengan relacion con registros de animales....un saludo
dejo abierta la pregunta por si quieres comentarme algo y despues la finalizo.....
- Compartir respuesta