Hacer un calculo al presionar un botón para todos los registros de la base de datos.
Nuevamente Neck y disculpas por las molestias que pueda ocasionar por las preguntas que formulamos.
Recientemente he creado una base de datos para determinar una nomina de pagos. Al presionar un botón se calcula un impuesto y otros calculos para otros campos.
La pregunta es: Como hacer para que al presionar un botón no solo afecte al registro actual con el que trabajamos, sino que lo haga con todos los registros de la base ya que ese procedimiento es igual para todos los registros (valga la redundancia). Asimismo preguntarte porque en ocasiones se tiene que presionar dos o tres veces el mismo botón (onclick) que he programado para que realice el calculo correcto. ¿Estare haciendo algo mal?
No se si seria mucha molestia el que te enviara mi base y le dieras un vistazo, talves es algo sencillo de resolver y no doy con bola, o prefieres que te coloque el codigo por aqui.
Como siempre espero tus acertados y sabios comentarios.
1 Respuesta
El tema de actualizar todos los registros se puede realizar a través de un recordset. Para ello necesitaría, inicialmente:
- El nombre de la tabla donde deben actualizarse los datos
- El nombre de los campos que intervienen en el proceso
- La fórmula para determinar el resultado final.
Por otra parte, el tema del click sí que, en principio, no sabría decirte sin saber qué se está haciendo exactamente.
De todas maneras, si lo que quieres es que se actualice la información de un campo calculado, podrías, al final del código (justo antes del End Sub), poner una línea de código así:
Me. Recalc
o, según en qué casos
Me. Refresh
Ya me dirás.
La tabla donde se actualizan los datos se llama nomina.
El nombre de los campos que intervienen para el calculo son:
ing_qnal
premio_punt
premio_asis
bono_prod
aguinaldo
la suma de los campos anteriores los asigno al campo texto200 y a partir de ahí comienza el calculo para un impuesto que voy y comparo con otra tabla llamada tablaimpuestos la cual ubico en un rango de valores. Para este calculo genere un botón llamado BtnCalcula el cual tengo declarado de la sig. manera.
Private Sub BtnCalcula_Click()
Dim vISTP, vSUBS, vInf, vSup, vCF, vExc, vImp, vDe, vHa, vPo As Variant
Dim rst As Recordset
vISTP = Me.texto200.Value
vSUBS = Me.texto200.Value
If IsNull(vISTP) Then Exit Sub
Set rst = CurrentDb.OpenRecordset("tablaimpuesto")
'Si la tabla esta vacía, bye bye
If rst.RecordCount = 0 Then GoTo salida
rst.MoveFirst
Do Until rst.EOF
vInf = rst.Fields("limite_inf").Value
vSup = rst.Fields("limite_sup").Value
If vISTP < vSup Then
If vISTP > vInf Then
vCF = rst.Fields("cuota_fija").Value
vInf = rst.Fields("limite_inf").Value
vSup = rst.Fields("limite_sup").Value
vExc = rst.Fields("excedente").Value
Exit Do
End If
End If
rst.MoveNext
Loop
Me.cuota_fija.Value = vCF
Me.limite_inf.Value = vInf
Me.limite_sup.Value = vSup
Me.excedente.Value = vExc
salida:
rst.Close
Me.Recalc
Set rst = Nothing
End Sub
Como te comente yo desearía que en otro botón no solo calcule el registro actual sino que lo haga con todos, que instrucción debo de seguir?
Gracias
Sin ver la tabla me es complicado darte una solución, porque intervienen bastantes variables, además de operaciones y otra tabla.
Voy a intentar responderte "de cabeza", apelando a mi "gran imaginación"... je, je.., por lo que te aconsejo que hagas la prueba en una copia de tu BD para no "cascar" los datos.
En el editor de VB insertas un módulo, y en él creas el siguiente procedimiento:
...
Public Sub calculaValores()
Dim Dim vISTP, vSUBS, vInf, vSup, vCF, vExc, vImp, vDe, vHa, vPo As Variant
Dim iq, pp, pa, bp,agui as variant
Dim vSuma as variant
Dim rstNom as recordset
Dim rst as recordset
Set rstNom=currentdb.openrecordset("nomina")
rstNom.movefirst
Do until rstNom.EOF
iq=nz(rstNom.Fields("ing_qnal").value,0)
pp=nz(rstNom.Fields("premio_punt").value,0)
para=nz(rstNom.Fields("premio_asis").value,0)
bp=nz(rstNom.Fields("bono_prod").value,0)
agui=nz(rstNom.Fields("aguinaldo").value,0)
vSuma=iq+pp+pa+bp+agui
If vSuma=0 then goto Siguiente
vISTP = vSuma
vSUBS = vSuma
Set rst = CurrentDb.OpenRecordset("tablaimpuesto")
'Si la tabla esta vacía, bye bye
If rst.RecordCount = 0 Then GoTo Salida
rst.MoveFirst
Do Until rst.EOF
vInf = rst.Fields("limite_inf").Value
vSup = rst.Fields("limite_sup").Value
If vISTP < vSup Then
If vISTP > vInf Then
vCF = rst.Fields("cuota_fija").Value
vInf = rst.Fields("limite_inf").Value
vSup = rst.Fields("limite_sup").Value
vExc = rst.Fields("excedente").Value
GoTo Edicion
End If
End If
rst.MoveNext
Loop
Edicion:
With rstNom
.Edit
.Fields("cuota_fija").value=vCF
.Fields("limite_inf").value=vInf
.Fields("limite_sup").Value = vSup
.Fields("excedente").Value = vExc
.update
End With
Siguiente:
RstNom. MoveNext
Loop
Salida:
Rst. Close
RstNom. Close
Set rst=Nothing
Set rstNom=Nothing
End Sub
...
Cuando necesites recalcular los datos, en un botón de comando, basta que escribas este código:
...
Private Sub...
Call calculaValores
MsgBox "Actualización realizada correctamente",vbInformation, "OK"
End Sub
...
Realmente, sin poder ver la BD, es complejo. Pruébalo, insisto, en una copia de tu BD y me comentas qué tal te ha ido.
Que tal Neck, he seguido los pasos que me indicaste y he adaptado el código a mi procedimiento.
A lo que veo y después de generar un botón para que me ejecute el código que he adaptado, algo anda mal que no realiza ninguna acción , solo el mensaje del Box.
Sigo intentando (tal vez este haciendo la cosas mal)...
¿Tienes posibilidad de enviarme sólo las tablas "nómina" (sin datos, más que un par de registros inventados de ejemplo) y "tablaimpuesto" (esta sí con datos)?
Es decir, crearte una BD y simplemente importar estas dos tablas (y ahí quitar los datos de la tabla nominas).
Mi correo es neckkito(ARROBA)yahoo(PUNTO)es
Lo ideal, si me lo puedes pasar, sería que en el mismo correo, por ejemplo, si me dejas tres registros de prueba, me indicaras los resultados finales que deberían reflejarse en los campos que te marco en negrita:
.Fields("cuota_fija").value=vCF
.Fields("limite_inf").value=vInf
.Fields("limite_sup").Value = vSup
.Fields("excedente").Value = vExc
Como verás el código es relativamente complejo e intervienen bastantes variables, por lo que quizás, al habértelo escrito "de cabeza", no "vea" alguna cosa que repercute en el código.
Bueno, ya me dirás.
Comprueba el mail al cual lo estás enviando, porque yo no recibo nada.
Neckkito(ARROBA)yahoo. Es
ARROBA = @
La envíe nuevamente, pero ahora de una cuenta de gmail.
Anteriormente la envíe por hotmail.
Espero y la recibas.
Saludos, gracias.
Que tal Neck, antes que nada deseo te encuentres bien.
Agradecerte por tus sabios consejos y ayuda.
Después de estar analizando el procedimiento que amablemente me has enviado y de hacer algunas pruebas para la validación de los cálculos, me encuentro con un detalle.
Una vez ingresando los 3 primeros datos en los primeros 3 campos (valga la redundancia) y al pasar al cuarto que es la fecha de ingreso y esta al dejarla vacía para probar la validación, me arroja el siguiente error:
Se ha producido el error 91 en tiempo de ejecución. Variable de objeto o bloque with no establecido.
Si selecciono depurar de la ventana de error de visual basic me manda al procedimiento
Salida:
rst.Close
rstImp.Close <-- aquí señala el error
rstSub.Close
dbs.Close
Set rst = Nothing
Set rstImp = Nothing
Set rstSub = Nothing
Set dbs = Nothing
Por lo demás esta excelente a como me lo has ilustrado.
Ya me dirás que hacer, gracias.
El error se te produce por intentar cerrar un recordset que aún no se ha abierto.
En el código del módulo, añádele lo siguiente (te marco un par de líneas, para que te ubiques, y lo nuevo te lo marco en negrita):
En la cabecera:
...
Public Sub calculaValores(vTrab As Long)
On Error GoTo sol_err
'Declaramos la variables para la SQL
Dim miSql As String
...
Al final del módulo:
...
Set dbs = Nothing
sol_salida:
Exit Sub
sol_err:
If Err.Number = 91 Then
Resume sol_salida
Else
MsgBox "Se ha producido el error " & Err.Number & " - " & Err.Description
End If
End Sub
...
A ver qué tal te va.
Excelentemente bien.
Muchas gracias nuevamente.
Aprovecho el momento (ya que es muy difícil encontrarte) solo para hacerte una pequeña pregunta, ya para finalizar.
Que consejo me puedes dar para poner en red esta miniaplicación (nomina). Leí en unos de tus artículos lo relacionado front-end back-end pero no me queda claro. Como tengo que preparar los entornos para que esto suceda o hacia donde tengo que migrar. Créeme que esto seria de gran ayuda para proceder con mis demás bases a ponerlas compartidas para varios usuarios, salvo tu mejor consejo y/u opinión.
Gracias Neck.
Un abrazo.
Me alegra que la cosa haya funcionado bien ;-)
La separación de una base de datos en front-end y back-end está ampliamente detallada por el propio Microsoft en la web. Los enlaces los tienes en el propio artículo que citas. Es decir, que no te voy a detallar el proceso aquí (sería de locos!).
Si me preguntas por una sistemática genérica, yo, lo que haría, sería lo siguiente:
- Realizar una compilación del código de VB (menú del editor de VB -> Depuración -> Compilar <nombreProyecto>). Corregir todos los errores que pueda mostrarte la compilación hasta que no quede ni uno (errores de este tipo pueden derivar en errores de separación de la BD).
- Compactar la base de datos (si no sabes de que hablo hay un artículo en la web, en el apartado Post-Access)
- Crearme una copia de la base de datos como backup original. Esta copia, para mí, intocable.
- Realizar el proceso de separación de la base de datos. Como resultado tendrías dos archivos: uno con tablas y otros con el resto de objetos (formularios, consultas, etc.)
- El archivo con las tablas será el que se quedará en el servidor; el otro será el que "repartirás" al resto de usuarios
- Fijarme un periodo de testeo (en función de complejidad de la base de datos y de tu propia valoración como administrador de la base de datos) para que los usuarios (o sólo algunos de ellos) utilicen la BD, para ver qué errores o comportamientos inesperados pueden producirse. Te comento lo de "algunos" porque a veces es conveniente que todos trabajen con el sistema "antiguo" y tengas unos "beta-testers" que manipulen el sistema "nuevo" con la finalidad de detectar errores.
- Si todo ha ido bien, y transcurrido el periodo que te has marcado como de prueba, implementar definitivamente el sistema.
Uffff... vaya rollo te he soltado. Espero que fuera la respuesta a la consulta que me hacías.
- Compartir respuesta