Esta es una de las cosas, que estuve años haciéndolo manual,
hasta que Patxi Sanz me enseñó a hacerlo, después con el paso del tiempo, me
doy cuenta que existen más formas de hacerlo, así que les voy a mostrar varias
de ellas, para este ejemplo conté con la colaboración de MexMan70. Veremos 7 formas diferentes que podemos llamar:
1.-Recordsetclone
directo
2.-Recordsetclone
con recordcount
3.-Recordsetclone
con absoluteposition
4.-En la
tabla con Recordset
5.-Consulta
con Execute
6.-Consulta
con DoCmd.RunSQL
7.-Desde el
subformulario
Vamos a
necesitar una tabla, le llamaremos Productos y constará de 4 campos id
Autonumerico, Nombre (texto), Precio (número) e Importe (número), y agregamos algunos
registros:
id | Nombre | Precio | Importe |
---|---|---|---|
1 | Tomate | 3 | 6 |
2 | Cebolla | 4 | 8 |
3 | Papa | 5 | 10 |
4 | Lechuga | 6 | 12 |
Creamos un
formulario en blanco, y en vista diseño
agregamos la tabla Productos y la dejamos caer dentro del formulario, nos
pregunta que nombre le queremos dar y le decimos que Subproductos, agregamos un
cuadro de texto y 7 botones, luego iremos cambiando los nombres, se ve más o menos así:
1.-Recordsetclone
directo
Podemos decir que Recordsetclone
es una copia de
la consulta o tabla de la que se basa el formulario y se usa para navegar y
realizar operaciones en los registros del formulario. Y si hacemos un bucle
podemos recorrerlos, nosotros lo haremos con Do Loop para ir
actualizando cada registro.
Ahora en vista diseño
vamos a ponerle de nombre: Cantidad al cuadro de texto y al primer botón lo
llamaremos RecordClone y en eventos al hacer click le damos a los 3 puntos y le
decimos que generador de código y nos lleva a vba, y entre Private Sub
RecordClone_Click() y End Sub ponemos:
With Me.SubProductos.Form.RecordsetClone
.MoveFirst
Do Until .EOF
.Edit
!Importe = !Precio * Me.cantidad
.Update
.MoveNext
Loop
End With
Podemos
probar nuestro primer Botón, poniendo algún número en el campo cantidad y dándole
al botón y debe verse parecido a esto:
2.-Recordsetclone
con recordcount
Es una
pequeña variante del anterior solo que ahora usaremos un For Next y contaremos
los registros con RecordCount asi que en el Botón segundo le cambiamos el
nombre a RecordCloneCount y de nuevo, nos vamos a eventos, al hacer click y generador
de código y ponemos:
Private Sub RecordCloneCount_Click()
Dim rs As DAO.Recordset
Dim i As Integer
Set rs =
Me.SubProductos.Form.RecordsetClone
If Not rs.BOF Then
rs.MoveFirst
For i = 1 To rs.RecordCount
rs.Edit
rs!Importe = Me.cantidad * rs!Precio
rs.Update
rs.MoveNext
Next i
End If
rs.Close
Set rs = Nothing
End Sub
Probamos el nuevo botón.
3.-Recordsetclone
con absoluteposition
Este es muy
parecido al primero solo que cuando lleguemos al final de los registros, nos
vamos a salir cuando AbsolutePosition sea igual al total de los registros. En
el tercer botón le cambiamos nombre y le ponemos RecordCloneAbsolute, y nos
vamos a eventos, al hacer click y generador de código y ponemos:
Private Sub RecordCloneAbsolute_Click()
With
Me.SubProductos.Form.RecordsetClone
.MoveFirst
Do
.Edit
!Importe = !Precio * Me.cantidad
.Update
If .AbsolutePosition = .RecordCount - 1 Then Exit Do
.MoveNext
Loop
End With
End Sub
Probamos el nuevo botón.
4.-En la
tabla con Recordset
Con un Recordset
directo en la tabla, también puede ser bastante fácil, en el cuarto botón le
cambiamos nombre y le ponemos Recordset, y nos vamos a eventos, al hacer click
y generador de código y ponemos:
Private Sub Recordset_Click()
Dim rs As DAO.Recordset
Set rs =
CurrentDb.OpenRecordset("SELECT id, Nombre, Precio, Importe FROM
Productos", dbOpenDynaset)
rs.MoveFirst
Do While Not rs.EOF
rs.Edit
rs![Importe] = rs!Precio * Me.cantidad
rs.Update
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Me.Refresh
End Sub
Probamos el nuevo botón.
5.-Consulta con Execute
Las
consultas son las formas más directas y quizás las más rápidas, podemos usar Execute
y DoCmd.RunSQL y usando variable o no,
vamos a ver la primera, en el quinto botón le cambiamos nombre y le ponemos CtaExecute,
y nos vamos a eventos, al hacer click y generador de código y ponemos:
Private Sub CtaExecute_Click()
Dim SQL As String
SQL =
"UPDATE Productos SET Importe = Precio * '" & Me.cantidad &
"'"
CurrentDb.Execute SQL, dbFailOnError
Me.Refresh
End Sub
Probamos el nuevo botón.
6.-Consulta
con DoCmd.RunSQL
Las
consultas son las formas más directas y quizás las más rápidas, podemos usar Execute
y DoCmd.RunSQL y usando variable o no,
vamos a ver la segunda y sin variable, en el sexto botón le cambiamos nombre y
le ponemos CtaRunSQL, y nos vamos a eventos, al hacer click y generador de código
y ponemos:
Private Sub
CtaRunSQL_Click()
DoCmd.RunSQL
"UPDATE Productos SET Importe = Precio * '" & Me.cantidad &
"'"
Me.Refresh
End Sub
Probamos el nuevo botón.
7.-Desde el
subformulario
Esta es una
idea de Patxi en la que en cada registro del subformulario tenemos que crear el
procedimiento que actualiza registro por registro y para poder usarlo en el
formulario principal declaramos el procedimiento como Public en el
subformulario. Entonces aquí primero tenemos que irnos al subformulario y en el
control Importe, eventos, después de actualizar, generador de código y Primero
cambiamos Private por Public y ponemos:
Public Sub
Importe_AfterUpdate()
Me.Importe =
Me.Precio * Me.Parent.cantidad
End Sub
Después en el
séptimo botón le cambiamos nombre y le ponemos Subform, y nos vamos a eventos,
al hacer click y generador de código y ponemos:
Private Sub Subform_Click()
Me.SubProductos.SetFocus
With Me.SubProductos.Form
.Precio.SetFocus
DoCmd.GoToRecord , , acFirst
Do While Not .NewRecord
.Importe_AfterUpdate
DoCmd.GoToRecord , , acNext
Loop
End With
End Sub
Y está listo para probarlo.
Puede bajar el archivo
Hola Emilio he usado la opcion uno para modificar un campo de un subformulario, pero me da error 2950 no entiendo porque. yo tengo access 2010. Alguna idea
ResponderBorrarHola uso todos los ejemplos u nada no me hace el recorrido por los registros, tengo 7 filas y solo pasa la primera y ahí se queda
ResponderBorrarEl 7 tiene error porque no puede ir al registros siguiente, el 2 funciona muy bien.
ResponderBorrarmuchas gracias ,me ayudo bastante.
ResponderBorrarpara el 7
lo hice de esta forma:
Private Sub act_Click()
Dim nro_reg As Integer
nro_reg = Me.N_F_Datos_Planilla_Notas_SUB.Form.Recordset.RecordCount ' nro de registros para el cicli
Me.N_F_Datos_Planilla_Notas_SUB.SetFocus
With Me.N_F_Datos_Planilla_Notas_SUB.Form
.N1.SetFocus
DoCmd.GoToRecord , , acFirst
Do While nro_reg > 1
.N1_AfterUpdate
DoCmd.GoToRecord , , acNext
nro_reg = nro_reg - 1
Loop
DoCmd.GoToRecord , , acLast
.N1_AfterUpdate
End With
End Sub
me funciono bien.
saludos.
donde N1 es un campo que tengo en el subformulario N_F_Datos_Planilla_Notas_SUB y que tiene su propia funcion.
ResponderBorrarBuenas noches... estoy trabajando con un Inventario de productos, pero al momento de actualizar el stock en la tabla productos me suma o resta la cantidad igual al numero de productos que tenga en el subformulario. no se que estare haciendo mal.
ResponderBorrarEl codigo que estoy empleando para recorrer el subformulario es el siguiente:
With Me.Subformulario_Detalle_Salida_Factura.Form.RecordsetClone
.MoveFirst
Do While Not .EOF
CurrentDb.Execute "UPDATE Productos INNER JOIN Detalle_Salida_Factura ON Productos.Cod_Productos = Detalle_Salida_Factura.Cod_Productos SET Productos.Stock = Productos.Stock - Cantidad WHERE Productos.Cod_Productos = Detalle_Salida_Factura.Cod_Productos;"
.MoveNext
Loop
End With
Le agradezco la ayuda que me pueda prestar.. soy novato en esto..