Añadir varios registros a un subformulario mediante selección múltiple con VBA

Escrito por Administrador

19 de noviembre de 2021

Hoy vamos a aprender cómo añadir varios registros a un subformulario mediante un formulario con selección múltiple usando VBA.

Esto es útil si disponemos de un listado, ya sea de materiales, servicios, personas... y queremos seleccionar varios registros para añadirlos de una sola vez al subformulario en lugar de tener que hacerlo uno a uno.

Para ello, he preparado un ejemplo (adjunto al final del post) en el que encontramos una tabla llamada "Servicios" con varios registros.

bloquear-access-fecha

También, usaremos la tabla "Temporal Servicios", en la que iremos añadiendo servicios conforme los seleccionemos en el formulario de selección múltiple. Asimismo, nos servirá para calcular el coste.

bloquear-access-fecha

Por otro lado, el formulario "Presupuesto" incluye el subformulario "Presupuesto_SubServicios" y en él visualizaremos los servicios añadidos al presupuesto.

bloquear-access-fecha

Finalmente, para añadir servicios, usaremos el formulario "Añadir servicio".

bloquear-access-fecha

En realidad, el código de VBA que nos interesa es el que lleva este último formulario, que va a controlar la selección múltiple de registros.

En primer lugar, al cargar el formulario, blanqueamos los campos "Horas" y "Seleccion" de la tabla "Servicios", para eliminar datos de cargas anteriores.

Private Sub Form_Load()

DoCmd.SetOrderBy "Servicio ASC"

'Blanqueamos la columna seleccion y horas de la tabla Servicios

Dim dbs As DAO.Database

Set dbs = CurrentDb()

dbs.Execute "UPDATE Servicios Set Horas='" & "" & "'"
dbs.Execute "UPDATE Servicios Set Seleccion='" & "" & "'"

End Sub

En segundo lugar, encontramos el código implementado en el evento "Al hacer clic" del botón Añadir, y que va a pasar los registros seleccionados al subformulario "Presupuesto_SubServicios" del formulario "Presupuesto".

Private Sub Añadir_Click()

Form.Refresh

'Seleccionamos los registros de la tabla Servicios que hayamos seleccionado

Dim rs As DAO.Recordset

Set rs = CurrentDb.OpenRecordset("Select * From Servicios where seleccion=True")

'Para cada uno de esos registros realizamos las siguientes operaciones

Do While Not rs.EOF

'Comprobamos que se ha rellenado el campo Horas

If (IsNull(rs!Horas) Or IsEmpty(rs!Horas)) And rs!Seleccion = True Then

MsgBox "Es necesario rellenar el campo horas"
GoTo error

End If

'Si ya hemos añadido el servicio hacemos un update, en caso contrario un insert

serv = DLookup("[Servicio]", "[Temporal Servicios]", "[Servicio] = '" & rs!Servicio & "'")

If IsNull(serv) Or IsEmpty(serv) Then

cSql = "Insert InTo [Temporal Servicios] (Servicio,horas,[precio coste],[precio total], PVP,[precio total pvp])" & _
"values ('" & rs!Servicio & "','" & rs!Horas & "','" & rs![Precio coste] & "','" & rs![Precio coste] * [Horas] & "','" & rs!PVP & "','" & rs![PVP] * [Horas] & "')"
CurrentDb.Execute cSql

Else

DoCmd.SetWarnings False
Form.Refresh
DoCmd.RunSQL "Update [Temporal Servicios] set [Horas]='" & rs!Horas & "',[Precio Total]='" & rs![Precio coste] & "' * '" & rs!Horas & "',[Precio Total PVP]='" & rs!PVP & "' * '" & rs!Horas & "' where [Servicio]='" & rs!Servicio & "'"
DoCmd.SetWarnings True

End If

Forms![Presupuesto]!Presupuesto_SubServicios.Requery

rs.MoveNext

Loop

rs.Close

Forms![Presupuesto]!Presupuesto_SubServicios.Requery

'Actualizamos el totalizador de servicios

Dim dbs As DAO.Database
Dim suma As Recordset
Dim suma2 As Recordset

Set dbs = CurrentDb()

Set suma = dbs.OpenRecordset("Select SUM([Precio Total]) as importeservicios from [Temporal Servicios]")
Set suma2 = dbs.OpenRecordset("Select SUM([Precio Total PVP]) as importeserviciosPVP from [Temporal Servicios]")

Forms![Presupuesto]!TotalServicios = suma!importeservicios
Forms![Presupuesto]!TotalServiciosPVP = suma2!importeserviciosPVP

DoCmd.Close

error:

End Sub

Vamos a ver cómo funciona el programa y el código paso a paso.

Para empezar, pulsa el botón Añadir servicio en el formulario "Presupuesto" y rellena el formulario "Añadir servicio" de la siguiente manera.

bloquear-access-fecha

El formulario "Añadir servicio" está asociado a la tabla "Servicios". De esta manera, cuando los seleccionamos e introducimos las horas de cada uno de ellos, estamos escribiendo directamente en la tabla.

Por eso, lo primero que hacemos es un recordset con los registros de la tabla "Servicios" que tienen el check del campo Seleccion en True.

bloquear-access-fecha

'Seleccionamos los registros de la tabla Servicios que hayamos seleccionado

Dim rs As DAO.Recordset

Set rs = CurrentDb.OpenRecordset("Select * From Servicios where seleccion=True")

A continuación, pulsamos el botón Añadir. Seguidamente, vemos que se han añadido 3h de albañilería y 5h de fontanería en el formulario "Presupuesto".

bloquear-access-fecha

Si volvemos a pulsar Añadir Servicio, y seleccionamos un servicio introducido previamente como el de Albañilería, el programa lo va a detectar y va a actualizar el campo horas con el nuevo valor.

Sin embargo, si el servicio no había sido añadido previamente, lo insertará con su correspondiente valor de horas.

También, comprobamos que esté relleno el campo "Horas" para los servicios seleccionados. A continuación, te dejo el link donde explico con más detalle cómo comprobar si se ha rellenado un campo obligatorio usando VBA, por si te interesa.

'Para cada uno de esos registros realizamos las siguientes operaciones

Do While Not rs.EOF

'Comprobamos que se ha rellenado el campo Horas

If (IsNull(rs!Horas) Or IsEmpty(rs!Horas)) And rs!Seleccion = True Then

MsgBox "Es necesario rellenar el campo horas"
GoTo error

End If

'Si ya hemos añadido el servicio hacemos un update, en caso contrario un insert

serv = DLookup("[Servicio]", "[Temporal Servicios]", "[Servicio] = '" & rs!Servicio & "'")

If IsNull(serv) Or IsEmpty(serv) Then

cSql = "Insert InTo [Temporal Servicios] (Servicio,horas,[precio coste],[precio total], PVP,[precio total pvp])" & _
"values ('" & rs!Servicio & "','" & rs!Horas & "','" & rs![Precio coste] & "','" & rs![Precio coste] * [Horas] & "','" & rs!PVP & "','" & rs![PVP] * [Horas] & "')"
CurrentDb.Execute cSql

Else

DoCmd.SetWarnings False
Form.Refresh
DoCmd.RunSQL "Update [Temporal Servicios] set [Horas]='" & rs!Horas & "',[Precio Total]='" & rs![Precio coste] & "' * '" & rs!Horas & "',[Precio Total PVP]='" & rs!PVP & "' * '" & rs!Horas & "' where [Servicio]='" & rs!Servicio & "'"
DoCmd.SetWarnings True

End If

Forms![Presupuesto]!Presupuesto_SubServicios.Requery

rs.MoveNext

Loop

rs.Close

Forms![Presupuesto]!Presupuesto_SubServicios.Requery

bloquear-access-fecha
bloquear-access-fecha
bloquear-access-fecha

Por último, actualizamos los totalizadores de precio que se encuentran en el pie del formulario.

'Actualizamos el totalizador de servicios

Dim dbs As DAO.Database
Dim suma As Recordset
Dim suma2 As Recordset

Set dbs = CurrentDb()

Set suma = dbs.OpenRecordset("Select SUM([Precio Total]) as importeservicios from [Temporal Servicios]")
Set suma2 = dbs.OpenRecordset("Select SUM([Precio Total PVP]) as importeserviciosPVP from [Temporal Servicios]")

Forms![Presupuesto]!TotalServicios = suma!importeservicios
Forms![Presupuesto]!TotalServiciosPVP = suma2!importeserviciosPVP

bloquear-access-fecha

Espero que hayas aprendido con este ejemplo cómo añadir varios registros a un subformulario mediante un formulario con selección múltiple usando VBA.

Por último, quiero invitarte a compartir tus dudas en los comentarios o en el foro. Intentaré ayudarte en todo lo que pueda, y así aprenderemos todos.

Hasta la próxima.

Si te ha servido y quieres donar

Descarga el archivo del ejemplo

7 Comentarios

  1. Avatar

    Hola! Muy buena página y he aprendido mucho. Ya que estas, si tienes tiempo, te aprovecho y si lo deseas además, me das una mano. Soy nuevo en esto de Access. Es largo jejeje!
    Tengo un “registro y recepción” en una MainForm y una Subform. La MainForm toma y carga los datos desde una tabla (datos del cliente) En la Subform -que esta enlazada con otra tabla por Nº de cliente- se muestra y se cargan los detalles de servicio a cada cliente. Ahora bien, tengo que generar una factura (que además será transformada luego a un txt con una estructura para facturación electrónica) desde “registro y recepción” (MainFrom) que contenga los datos y los servicios (Subform). Pero no todos lo servicios se facturan, ya que algunos se han pagado ya (recordar que es un registro también) entonces tengo que seleccionar los servicios que se van a pagar en ese momento e incluso poder editarlos si es en efectivo. Que hice yo:
    Primer modelo
    Lo primero desde mi ingenuidad fue pasar todo los datos de la Mainform a un textbox a la factura. Pero no podía pasar los datos de una Subform a los textbox o al menos no sabía. Si lo lograba, aunque seria poco práctico, se borraba lo que no se facturaría en la factura y listo. Pero no hubo forma de pasar todos los datos de la subfom a multiple texbox. Solo el primer registro lograba pasar.
    Segundo Modelo
    Luego fue aprendiendo e hice un botón en la Mainform y repliqué la misma relación original del “registro-recepcion” en otra MainForm y Subform pero con forma de factura. Sin embargo, aun me figuran todos los servicios. Hasta que me encontré con tu tutorial y la selección.
    Entonces esa subform del presupuesto temporal que enseñas me sirvió para seleccionar desde la subform de servicios (le agregue un seleccionador) lo que se querían solo facturar. Se la integre al primer modelo (La mainform con los textboxes) y pudo funcionar. Tenia la factura y los servicio. Pero imposible generar un reporte o algo así. Tengo que integrar a la subform temporal al segundo modelo no? Esos texboxes del primero modelo me parece que no sirve aunque son rápido.
    Ahora tengo que generar un archivo txt, guardar todos los datos de la factura en una tabla y otras cosas mas.
    Bueno, muchisimas gracias profe!

    Responder
    • Avatar

      Hola Luis!

      No sé por qué no te llegó a funcionar el primer modelo porque ibas bien encaminado. Probablemente no estabas pasando el array completo y por eso sólo se registraba el primer valor en el textbox. En cualquier caso, me alegra saber que fuiste capaz de usar una segunda vía poniendo en práctica lo que explicaba acerca de la selección múltiple de registros.

      Para exportar la información a un archivo txt, te aconsejo primero que elabores un informe y luego lo exportes en dicho formato. Así, es todo más sencillo.

      Si quieres, puedes abrir un hilo en el foro y subir un ejemplo del programa que estás construyendo para poder ayudarte con más detalle.

      Un saludo.

      Responder
      • Avatar

        Muchisimas gracias por tus consejos! hare lo que me dices! abrazo grande!

        Responder
        • Avatar

          De nada. Para cualquier cosa, por aquí andamos. Saludos.

          Responder
  2. Avatar

    Hola! como estas administrador? gran trabajo pero sabes que me tira un error: access cannot find the referenced "Presupuesto" Me parece porque no esta abierta. La intentado abrir con DoCmd.open pero nada. Desde ya gracias!

    Responder
    • Avatar

      ya esta! lo que pasa es que abría primero añadir servicio. Y primero se tenia que abrir presupuesto! existe alguna linea para poder abrir primero añadir servicio? Muchas gracias!

      Responder
      • Avatar

        Hola Luis,

        El formulario principal del programa es "Presupuesto", y "Añadir servicio" es una formulario que nos va a ir agregando servicios sobre el primero. ¿Qué quieres hacer exactamente?

        Saludos.

        Responder

Enviar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Últimas publicaciones

Categorías

febrero 2024
LMXJVSD
 1234
567891011
12131415161718
19202122232425
26272829 

Debates en el foro

Avatar
Access en una sola ventana
Avatar
Versiones frontend

Contacto