Hola
Tengo una base de datos con una estructura un poco compleja.
Por un lado tengo una tabla, llamada 'Clientes', con tres campos: 'Identificador Cliente' [autonumérico], 'Nombre Cliente' [texto] y 'Id de categoría' [entero]
Una segunda tabla se llama 'Personas Clientes' y tiene 4 campos: 'Id' [autonumérico], 'Nombre', 'Apellidos' [textos] y 'Comentario' [memo]
Una tercera tabla se llama 'Historial Personas Clientes', y tiene muchos campos, entre los que destacan: 'Id' [autonumérico], 'Id Persona' [Entero], 'Fecha inicio' [fecha], 'Id Cliente' [entero]
Estas tablas están relacionadas de manera que en la tercera, el campo 'Id Persona' se corresponde con el campo 'Id' de la segunda tabla, y el campo 'Id Cliente' se corresponde con el campo 'Identificador Cliente' de la primera.
Cuando doy de alta un cliente nuevo, debe darse de alta también un contacto nuevo. Esto implica que una nueva entrada en la tabla 'Clientes' debe crear, por código, un registro en 'Personas Clientes' y otro en 'Historial Personas Clientes'
Lo que hago es lo siguiente:
Cuando pincho en el botón de crear cliente, se abre un formulario que lo llamo con la propiedad acEdit para que no me limite exclusivamente a añadir.
En el evento Open del formulario compruebo unas condiciones que si se dan (en este caso se dan), termina con un
me.recordset.addnew
Hasta ahí parece que todo funciona bien.
Posteriormente relleno los controles para introducir los datos de la tabla 'Clientes'
Y tengo un botón de "Guardar cambios"
Ahí pongo este código
Private Sub GuardarCliente_Click()
Dim rst, rst2 As Recordset
Dim Nombre As String
Dim Id As Integer
Id = Me.Recordset("Identificador Cliente")
Me.Nombre_cliente.SetFocus
Nombre = Me.Nombre_cliente.Text
Me.Recordset.Update <----------------Esta es la tabla 'Clientes'
Me.Recordset.AddNew
Form.Tag = ""
Set rst = [Form_Personas Clientes].Recordset <----------Esta es la tabla 'Personas Clientes'
rst.AddNew
rst("Nombre") = "Genérico"
rst("Apellidos") = Nombre
Set rst2 = [Form_Subformulario Historia Clientes].Recordset <----------Esta es la tabla 'Historial Personas Clientes'
rst2.AddNew
rst2("Id Persona") = rst("Id")
rst2("Fecha inicio") = Date
rst2("Id Cliente") = Id
rst.Update
rst2.Update
Set rst = Nothing
Set rst2 = Nothing
End Sub
En primer lugar, esto no parece una estructura de datos muy complicada.
En segundo lugar veo que has puesto espacios en los nombres de los campos. Nada recomendable, porque tendrás que poner comillas y corchetes en bastantes lugares.
Sobre el registro en blanco, le estás diciendo que lo cree con
Me.Recordset.Update ' guardas el primero
Me.Recordset.AddNew 'creas uno en blanco
Si el el Id es autonumérico puede que no se asigne hasta que no guardes el registro.
yo cambiaría el orden
Primero guardaría el registro,
luego seguiría con todo lo demás
¿Realmente necesitas el addnew dentro del código para guardar el cliente?
si quieres dejar el formulario en blanco para el siguiente registro hazlo al final del todo
No sé.
------
Ya sé Excel, pero necesito más.
Gracias, intentaré darle una vuelta.
Primero: es complicado para mí, porque mi estructura mental da para esto de refilón ;)
Segundo: necesito poner el addnew para que el usuario sepa que se ha realizado la grabación. Me parece la mejor manera. Pero sí puedo ponerlo al final, cuando vacíe las variables.
Tercero y no menos importante: El registro blanco se me guarda primero. Ese update guarda lo que tengo en los controles. El problema es que, de alguna manera, se graba el registro en blanco. Tiene que ser antes de ese update, que debería volcar los datos de los controles a su registro, como parece que hace.
¿O me estoy equivocando en algo?
Un saludo
Como me estoy volviendo loco, he intentado simplificar al máximo. He creado una BD que tiene una tabla con dos registros: uno autonumérico y otro de texto.
He creado un formulario con dos botones, un textbox y un listbox.
Al listbox le he puesto el siguiente código, para que salga la lista de datos:
SELECT (Id & ", " & Nombre) AS Cliente
FROM Tabla1
ORDER BY Tabla1.Nombre;
para mover el cursor al último registro modificado de un recordset, puedes utilizar lo siguiente:
rs.Bookmark = rs.LastModified
donde rs es el recordset
------
Ya sé Excel, pero necesito más.
Lo que me pasa es paranormal, creo yo.
La cosa es muy sencilla. Tengo un control en un formulario. Dejo activos los selectores de registro del formulario para moverme libremente.
El formulario tiene correctamente asociada la tabla. El control tiene correctamente asociado el campo.
Abro el formulario con la orden:
DoCmd.OpenForm "Clientes1", acNormal, , , acFormEdit, acDialog
Puede esto tener que ver con que tengo abierta la misma tabla a la vez en dos formularios diferentes?
Puede tener que ver con que estás utilizando directamente el recordset que utiliza el formulario
prueba a utilizar RecordsetClone, es otra propiedad del formulario que devuelve otro recordset con los mismo datos, pero si te mueves alante o atras o insertas, etc, el formulario no se mueve, se queda en el mismo registro que estaba.
set rs = me.recordsetclone
------
Ya sé Excel, pero necesito más.
Y eso me permitirá añadir datos nuevos a la tabla?
No lo he hecho antes por eso...
No sé si está resuelto ya o no, pero el problema está acotado.
He creado una aplicación simple para actualizar una tabla. Funciona.
He cambiado la tabla y he hecho referencia a la tabla 'Clientes'. NO funciona.
Con lo que deduzco que el problema está en la tabla.
He probado a usar la recuperación de Access, pero no corrige nada.
Probaré a exportar los datos a excel, rehacer la estructura de tablas desde cero y repoblarlas con los datos desde excel, teniendo el cuidado de que al introducir los campos de nuevo, los autonuméricos no coincidirán: encaje de bolillos con excel, pero como ya sabemos en este foro, excel se deja manejar ;)
Saludos y muchas gracias por la ayuda. No era fácil, pues no era normal que ocurriera.
Bueno, como esto es ya para nota, dejo la solución casi definitiva.
No he sido capaz de hacer que funcione correctamente mediante operaciones normales.
Así que saco la artillería.
Desvinculo totalmente los controles de la tabla e inserto los datos a mano vía sentencia SQL así:
Set dbs = CurrentDb
strSQL = "INSERT INTO Clientes ([Nombre cliente], [Id de categoría]) VALUES ('" & Texto0.Text & "', " & Cuadro_combinado9.Value & ")"
dbs.Execute strSQL
Código final:
Private Sub GuardarCliente_Click()
Dim merst As Recordset
Dim Nombre As String
Dim Id, Id1 As Integer
Set merst = Me.Recordset
Me.Nombre_cliente.SetFocus
If Not (IsNull(Me.Nombre_cliente.Text) Or Me.Nombre_cliente.Text = "") Then <------ Nombre_cliente es el textbox
If Not (IsNull(Me.Cuadro_combinado7.Value)) Then
Nombre = Me.Nombre_cliente.Text
Set dbs = CurrentDb
strSQL = "INSERT INTO Clientes ([Nombre cliente], [Id de categoría]) VALUES ('" & Me.Nombre_cliente.Text & "', " & Me.Cuadro_combinado7.Value & ")"
dbs.Execute strSQL
Me.Undo <--------------para que vuelva a poner todo en blanco y que no le dé por guardar como debería hacer (y que no hace)
Id = DLookup("[Identificador Cliente]", "Clientes", "[Nombre cliente] = '" & Nombre & "'")
strSQL = "INSERT INTO [Personas Clientes] ([Nombre], [Apellidos]) VALUES ('Genérico', '" & Nombre & "')"
dbs.Execute strSQL
Id1 = DLookup("[Id]", "[Personas Clientes]", "[Nombre] = 'Genérico' AND [Apellidos] = '" & Nombre & "'")
strSQL = "INSERT INTO [Historial Personas Clientes] ([Id Persona], [Fecha inicio], [Id Cliente]) " _
& "VALUES (" & Id1 & ", date, " & Id & ")"
dbs.Execute strSQL
Else
Me.Cuadro_combinado7.SetFocus
Me.Cuadro_combinado7.BackColor = RGB(255, 255, 153)
End If
Else
Me.Nombre_cliente.SetFocus
Me.Nombre_cliente.BackColor = RGB(255, 255, 153)
End If
Actualiza
Set merst = Nothing
Set dbs = Nothing
End Sub
gracias por compartir la solución final.
------
Ya sé Excel, pero necesito más.