Campo "Existencias" con campo de entrada y campo de salida de datos

Un formulario "Recargas" con un campo "Cantidad"(en el campo cantidad anoto los litros que llegan en el cisterna y se vacian en un tanque. En otro formulario "ARQUEOS" con un campo "LitrosVendidos" (litros que vende o dispensa una manguera de un surtidor conectada al tanque anterior). En el formulario Recargas le adigciono un campo llamado "Existencias" que sume las entradas de combustible al tanque y que al mismo tiempo reste los "LitrosVendidos" que dispensa la manguera, para que me diga al final de cada turno cuantos litros me quedan disponibles en el tanque para el siguiente turno.

¿Se puede hacer esto?

Respuesta
1

La respuesta es muy didáctica pero en mi caso haría todo el movimiento en una sola tabla, necesitaría las siguientes tablas

TABLAS

Tabla Proveeodores

Idproveedor

nombre_prov

etc...

Tabla tblmangeras

Idmangera

Descripcion

Tabla Depósitos

Iddeposito

nombre_deposito

Capacidad

etc... más campos

Tabla Movimientos

Idmovto

Idmangera

Iddeposito

Idproveedor (solo se afecta si el tipo de movimiento es 1)

tipo (1=Entrada 2= Salida)

fecha_movto

Cantidad

Saldo (opcional... se puede obtener con una consulta)

ect... más campos

Y puede actualizar aplicando lo que bien le explicaron. Aunque no utilizo Dlookup() ni DLast() prefiero mediante sentencias SQL, así no tendría mayores cambios cuando migre a un servidor de datos como postgreSQL.

Bueno esto es una forma siguiendo un sistema relacional. Personalmente lo utilizo en mis programas de inventarios.

1 respuesta más de otro experto

Respuesta
1

Si me permites, yo no lo haría así. Luego te lo explico.

Según dices, si tengo la tabla Recargas y el formulario basado en ella

Anoto los litros de recarga y cuando pulso Enter

Otro día vienen a recargar y lo mismo

En este caso, el código del evento Después de actualizar del cuadro de texto Litrosrecarga sería

Private Sub LitrosRecarga_AfterUpdate()
DoCmd.RunCommand acCmdSaveRecord
Existencias = Nz(DLast("existencias", "recargas", "idrecarga<" & Me.IdRecarga & "")) + LitrosRecarga
End Sub

Lo del Nz es porque se supone que antes de la primera recarga el depósito estará vacío.

Vamos con los arqueos

Cuando pulso Enter

Otro día

En este caso el código del evento Después de actualizar del cuadro de texto Litros Vendidos es

Private Sub LitrosVendidos_AfterUpdate()
Existencias = DLast("existencias", "recargas") - LitrosVendidos
DoCmd.RunSQL "update recargas set existencias=existencias-litrosvendidos where idrecarga=dlast(""idrecarga"",""recargas"")"
End Sub

Y ahora te digo porque no lo haría. Si miras la tabla Recargas verás

Parece un contrasentido, ha tenido dos descargas por 45000 litros, pero en existencias sólo hay 42450( eso se considera fraude, o que el empleado roba combustible, es broma).

Verás, es opinión mía, tu tienes UN depósito, con unas características, capacidad, número de serie, etc. Luego tienes VARIAS recargas y VARIAS salidas de combustible.

Yo crearía una tabla Depósitos( porque puede haber más de uno) con los campos que sean necesarios sin poner el campo Existencias, pondría en el formulario un campo independiente que me mostrara las existencias de la tabla Depósitos. Luego otra tabla Recargas con su formulario y otra tabla Arqueos con su formulario.

¿Que luego quieres saber los litros que han entrado en un mes, en un depósito, en una semana, etc, para eso tienes la tabla Recargas. ¿Que quieres saber cuantos litros has vendido en un mes, entre fechas, por surtidores, etc para eso tienes la tabla Arqueos.

Y mientras tanto las existencias reales siguen estando en la tabla Depósitos

Si quieres, me lo dices y te preparo un ejemplo de como lo haría.

Estaría enormemente contento y agradecido si me lo puedes ofrecer pues para que lo pueda hacer de la manera más fiable posible, gracias anticipadas

Parto de la premisa que cuando se empieza los depósitos están vacíos, si no lo estuvieran bastaría con poner en el campo Existencias de la tabla Depósitos los litros que contienen.

Tengo una tabla Depositos

Le he puesto capacidad por ponerle algo, pero se debería poner Stock Mínimo, para que cuando fueras a vender e igualaras o rebasaras el stock mínimo te avisara o le mandara un email al proveedor para que te reponga.

También tengo las tablas Recargas y Salidas, a las que le he añadido dos campo, que no hacen falta para nada, pero es más didáctico. En Antes, te pondrá las existencias de ese depósito Antes de recargar o dar salida, y en Después, las nuevas existencias después de recargar o dar salida

Como partimos de la idea de que en principio los depósitos están vacíos vamos a recargar

Anoto la fecha( o lo que hubiera que anotar) y elijo el depósito A1. En el momento que lo elija, en Antes me pone 0 porque hemos dicho que no hay nada

 Cuando pulso Enter

Y me deja la tabla Depositos como

Sigo rellenando y

Como puedes ver da igual el orden, que en Después aparecen los valores correctos ya que quien "dirige" los cálculos es el IdDeposito

El combinado Deposito, en el origen de la fila tiene dos columnas, el IdDeposito(columna dependiente) y Deposito de la tabla Depositos, pero sólo muestra el Deposito.

En este caso, el código del evento Después de actualizar del combinado Iddeposito es

Private Sub IdDeposito_AfterUpdate()
Antes = Nz(DLookup("existencias", "depositos", "iddeposito=" & Me.IdDeposito & ""))
Cisterna.SetFocus
End Sub

Y el código del evento Después de actualizar del cuadro de texto LitrosRecarga es

Private Sub LitrosRecarga_AfterUpdate()
DoCmd.SetWarnings False
Despues = Antes + LitrosRecarga
DoCmd.RunSQL "update depositos set existencias=despues where iddeposito=" & Me.IdDeposito & ""
End Sub

Le pongo lo de Docmd.setwarnings para que no te aparezca la dichosa ventanita de "Va a actualizar...."

Como no me deja poner más imágenes continuo en la ampliación

Continuamos ahora con las recargas

Anoto la fecha y en el momento que elijo un surtidor, en Antes me pone los litros que hay en ese surtidor hasta ese momento

Anoto los litros de salida y cuando pulso Enter

Y la tabla me la deja

Ya me ha recogido las nuevas existencias

Hago otra salida

Y la tabla

En este caso el código es

Private Sub IdDeposito_AfterUpdate()
Antes = DLookup("existencias", "depositos", "iddeposito=" & Me.IdDeposito & "")
LitrosSalida.SetFocus
End Sub
Private Sub LitrosSalida_AfterUpdate()
Despues = Antes - LitrosSalida
DoCmd.RunSQL "update depositos set existencias=existencias-litrossalida where iddeposito=" & Me.IdDeposito & ""
End Sub

También podría poner en vez de Existencias-litrossalida, simplemente Despues

Se podría poner como formulario único, pero creo que continuo es más didáctico, porque se ve como va "arrastrando" las cantidades.

Esto deberías completarlo con un formulario Principal (desde donde "dirigir" todas las operaciones), y poner, por ejemplo, un botón para que te abra los formularios en un registro nuevo. Para saber lo que ha entrado en un deposito en un mes, entre fechas, etc, y lo mismo para Salidas. Se puede hacer en informes, gráficos, mensajes, etc.

Hola, tu propuesta funciona muy bien y es muy de mi agrado, gracias.!

Solo hacerte una pregunta más sobre este tema. Funcionando todo bien, el problema que me surge es que el valor de "LitrosSalida" se me genera en otro campo de otro formulario llamado lecturas donde a través de las lecturas que me proporciona el surtidor calculo los litros de venta o salida totales del turno. Y no se como llevar (ni siquiera se si se puede) este valor al campo LitrosSalida

Sin que haya que tipearlo a mano de nuevo (pretendo reducir problemas de taipeo y transmisión de datos). Espero haberme explicado bien. Muchas gracias de nuevo.

Al no saber como están construidas las tablas es difícil concretar. Pero vamos a suponer, que en esa otra tabla el valor que te interesa trasladar es el del campo LitrosSalida(por poner un nombre) de la tabla Lecturas. Bastaría con poner, en el evento Después de actualizar del combinado Depósito del formulario Salidas

Private Sub IdDeposito_AfterUpdate()
Antes = DLookup("existencias", "depositos", "iddeposito=" & Me.IdDeposito & "")
LitrosSalida=dlast("litrossalida","lecturas","iddeposito=" & me.iddeposito & "")
Despues = Antes - LitrosSalida
DoCmd.RunSQL "update depositos set existencias=despues where iddeposito=" & Me.IdDeposito & ""
End Sub

Me explico, una vez elegido el depósito, en antes te pone las existencias hasta ese momento, en litrosSalida te pone el valor que hay en el campo LitrosSalida del último registro de la tabla Lecturas, en que el campo Iddepósito sea igual al que acabas de seleccionar en el formulario.

En Después te `pone la diferencia

Y por último, te actualiza las existencias de ese depósito de la tabla Depósitos a las nuevas.

Hola de nuevo. Surgió otro improvisto para mi funcionando todo como dijiste, el problema esta que cuando se selecciona el deposito en el combo todo va bien si se selecciona un deposito y no te equivocas pues el programa corre, a la que vuelves a introducir el tanque para corregir el error de introducción de datos vuelve a correr el programa y así cuantas veces se haga aunque las lecuras de donde sale el TotalLitros se haga una sola vez. En resumen funciona bien la primera vez, si uno mete el deposito bien a la primera pero si uno se equivoca y mete el equivocado el programa corre igual y las existencias se falsean por completo. Se podría mejorar este caso. Muchas gracias de nuevo.

Cuando saltas de un piso 15 ya no valen los arrepentimientos. En el evento Antes de actualizar del combinado Depósito podrías poner

dim respuesta as byte
respuesta=msgbox("¿Está seguro de que es el depósito correcto?, luego no valen los arrepentimientos",vbyesno,"Piénsalo bien?
if respuesta=vbyes then
Exit sub
else
docmd.cancelevent
end if

Me explico, si eliges un depósito te aparece el mensaje pidiendo confirmación. Si le dices que si, sigue con el procedimiento que te había puesto en la otra respuesta, la del evento Después de actualizar. Si le dices que no, el cursor se vuelve a Depósito para que cambies el valor.

De todas formas, también se podría corregir recalculando todo, pero para eso habría que saber como son tus tablas. Por ejemplo, se le podría decir

dim i as integer

for i=1 to me.recordset.recordcount

...

Pero vuelvo a que hay que saber como son tus tablas y los formularios.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas