Código para actualizar campo de tabla mediante formulario access
Tengo un formulario para dar de baja a los socios con un combo llamado cboSocio donde hace referencia a todos los socios que hay dados de alta y el valor que guarda es el código de socio y un texbox llamado Fecha baja, y lo que quiero es que para dar de baja un socio simplemente elegir el socio en concreto que necesito y poner la fecha en el otro texbox y un botón que al hacer click genere un código que el valor que hay en el campo fecha baja se inserte en el campo Fecha baja de la tabla TSocios filtrado claro esta por el código socio (que estaría reflejado en el cboSocio).
1 Respuesta
Este es el código que necesitas para tu botón:
Dim miSQL as String
miSQL="UPDATE TSocios SET [Fecha Baja]=#" & Format(Me.Fecha_baja,"mm/dd/yyyy") & "# WHERE [Codigo Socio]=" & Me.cboSocio
CurrentDb. Execute miSQL
Ojo con los nombres de los campos y controles.
Como siempre funciona perfectamente, el formulario no esta asignado a ninguna tabla y el combobox cboSocio es independiente aunque coja los valores de la Tabla TSocios, asi que si yo quisiera que en el cbo solo me diera los socios que estan dados de alta deberia de basar el formulario en una consulta sobre la tabla TSocios con los campos codigo socio ; Fecha Baja y en esta la condicion Falso.
o por el contrario es el cbo lo que tendria que basar en la consulta que te acabo de comentar y si haria falta algun campo mas
Un saludo
En el origen del cboSocios (que es una sentencia SQL, es decir, una consulta) puedes hacer los filtros que necesites, en tu caso que te muestre los dados de alta. Sería algo así:
SELECT CodigoSocio, Nombre FROM TSocios WHERE Alta=True
Suponiendo que tienes un campo llamado Alta de tipo Si/NO
Me refería como tu dices sí lo filtro ya en la consulta del cboSocio y hay en el campo fecha baja en criterio poner false no?
Es lo que te digo, tienes que hacer el filtro en el propio origen del combo.
Ahora bien, parece (por lo que comentas) que no tienes un campo Sí/No para saber si un socio está de alta o no (llamado Alta o Baja), que sería lo normal, sino que sabes si un socio está de alta cuando en el campo (de tipo fecha) FechaBaja no hay valor, y está de baja en caso de que haya una fecha en dicho campo.
En este caso, la SQL del combo, podría ser así: SELECT CodigoSocio, Nombre FROM TSocios WHERE IsNull(FechaBaja)
Esto es lo que tengo en el origen de la fila ahora mismo:
SELECT TSocios.[Codigo Socio], TSocios.id, TSocios.Nombre FROM TSocios ORDER BY TSocios.[Nombre]; (Que por cierto al despegar el cbo los valores que veo son el Id y Nombre no como yo elegí al ahora de hacer el combo que puse el Codigo Socio y Nombre ordenado ascendente por nombre, aunque a la hora de actualizar lo hace bien pero puede confundir ya que el id a veces puede no coincidir con el numero de socio).
A ver...
El origen del combo que tienes coge los campo Codigo Socio, id y Nombre de la tabla TSocios y los ordena por Nombre (eso es lo que significa el SELECT). Lo de que te muestre sólo id y nombre es por cómo lo tienes configurado: en la pestaña Formato del cuadro combinado, verás un propiedad "Número de columnas" que tendría que estar en 3 (que son los campos del SELECT) y debajo otras que es "Ancho de columnas". En ésta es dónde configuras el ancho de cada una de ellas, en el orden en que aparecen en el SELECT. En tu caso imagino que el primer valor será 0, y por eso no se te ve la columna Codigo Socio. Ahí tendrás que ponerlo a tu gusto.
Otra opción sería eliminar el id del SELECT, si al final el valor que guardas es el Codigo Socio... pero igualmente deberás adaprtar esas propiedades de las columnas.
Hay otra propiedad relativa a las columnas: "Columna dependiente", que indica cual es la columna de la que se va a guardar tu valor (en tu caso debiera ser 1)
Para añadirle el filtro, tienes que añadirle un WHERE:
SELECT TSocios.[Codigo Socio], TSocios.id, TSocios.Nombre FROM TSocios WHERE [Fecha Baja] Is Null ORDER BY TSocios.[Nombre];
Pero aún así, sería recomendable que añadieras un campo Baja, de tipo Sí/No, y así es más sencillo hacer el filtro:
SELECT CodigoSocio, Nombre FROM TSocios WHERE Baja<>True
Y en el código para actualizar le añades ese campo:
Dim miSQL as String
miSQL="UPDATE TSocios SET [Fecha Baja]=#" & Format(Me.Fecha_baja,"mm/dd/yyyy") & "#, Baja=True WHERE [Codigo Socio]=" & Me.cboSocio
CurrentDb. Execute miSQL
Si ya modifique la columnas para que se vea lo que quiero y ahora ya se ve el código socio y el nombre en el cboSocio y no filtra bien y además no me deja seleccionar nada, he añadido el campo baja si/no a la tabla TSocios como me dijiste y cambie la sql en el evento del comando. En esta bd solo va el formulario baja y la TSocios.
no te filtra bien, porque el filtro lo tienes puesto para los que están de baja: WHERE (((TSocios.[Fecha Baja]) Is Not Null));
Para que te filtre los que están de alta, te sobra el Not:
WHERE (((TSocios.[Fecha Baja]) Is Null));
Si añades el campo Sí/NO, tienes que marcarlo tb en la tabla para los que ya tienen fecha de baja.
Como te comentaba, el filtro del combo es más sencillo hacerlo sobre el campo Sí/NO:
WHERE TSocios.Baja<>True
El tema de que no te deje seleccionar un valor en el combo, es porque le tienes asignado como origen del control un supuesto campo llamado " " (un espacio en blanco). Imagino que sería porque no borraste correctamente su origen. Eso lo puedes ver en la vista diseño, que verás el cbo en blanco, mientras que el cuadro de texto pone "independiente". Si le borras ese espacio en blanco, ya te va.
Otro fallo que le acabo de ver, es que el cuadro combinado coge el valor del id del socio (columna dependiente: 1), mientras que el código vba actualiza la tabla en función del código socio, por lo que a menos que id y código socio coincidan, no se te va a actualizar la tabla.
O bien le quitas el campo id al SELECT del combo, o le cambias la columna dependiente a la 2, o modificas el código vba para que actualice en función del ID [WHERE Id=" & Me.cboSocio], o modificas el código vba para que coja el valor de la columna correspondiente al código del socio [WHERE [Codigo Socio]=" & Me.cboSocio.Column(1) ]
lo he solucionado poniendo en el origen de la filadel cboSocio:
SELECT TSocios.id, TSocios.[Codigo Socio], TSocios.Nombre, TSocios.[Alta/Baja] FROM TSocios WHERE (((TSocios.[Fecha Baja]) Is Null)); y cambie columna dependiente la 2 y funciona bien.
Pero en el botón aceptar he cambiado el código por este que me dijiste:
Private Sub cmdAceptar_Click()
Dim miSQL As String
miSQL = "UPDATE TSocios SET [Fecha Baja]=#" & Format(Me.Fecha_Baja, "mm/dd/yyyy") & "#, Baja=True WHERE [Codigo Socio]=" & Me.cboSocio
CurrentDb.Execute miSQL
MsgBox "El Usuario ha sido dado de baja", vbInformation, "AVISO"
DoCmd.Close acForm, Me.Name
DoCmd.OpenForm "FMENU"
End Sub
pero me da error 3061 en tiempo de ejecución . pocos parámetros. se esperaba 1.
y marca la linea
CurrentDb.Execute miSQL
para que cuando se de el socio de baja actualice la fecha y marque el check.
Debido a tu experiencia bastante más amplia que la mía y como ya viste más o menos la bd, me podrías decir como estructurarla mejor (como incluir el campo Alta/Baja etc...) para un buen funcionamiento.
Por ejemplo con ese campo quien está de alta o baja seria sencillo saberlo basando una consulta sobre el.
¿Mi idea era dar de baja así los socios pero estoy pensando si se vuelven a dar de alta seria editar el usuario y borrar campo fecha y desmarcar el check pero seria interesante poder saber siempre cuando se dio de baja y de alta tantas veces como fuesen como se podría hacer? (No se si sera la mejor opción pero se me ocurrió el poder crear una tabla que tuviese los campos id(auto); código socio; fecha alta y fecha baja, ¿pero cómo se rellenarían esos campos varias veces ese es la cuestión que por más vueltas que le doy no llego je je) y por ejemplo para los pagos esta bien pero creo que faltaría otro campo que fuese año no? Y modificar el que se creo como me dijiste que filtra por código socio y que filtre también por el de año.
Cosas que fueran interesantes que se vean a simple vista ahora que esta en elaboración y proceso de maduración.
Gracias de antemano por todo.
Algo has debido de cambiar que no debías, porque el código funciona perfectamente (comprobado sobre tu bd con los cambios que comentas, puedes verlo aquí)
En cuanto a la otra parte, si quieres tener un registro de las situaciones (altas y bajas de un mismo socio), tendrás que hacer una tabla nueva en la que recojas el identificador del socio, la situación y la fecha, y cada vez que se modifique la situación del socio, añades un nuevo registro a esa tabla.
También te puede interesar hacer lo mismo con las cuotas (puede ser que un socio cambie de tipo de cuota varias veces y quieras mantener un histórico). En la BD te va cómo lo haría yo, más o menos, pues yo lo haría por el id (que es la clave principal y permite optimizar las relaciones)
Estoy ojenado la propuesta y en la tabla TSociosSvein y quitaste ciertos campos (Fecha alta, fecha baja, altaa/baja (TSituacion); tipo de cuota, concepto e importe, descuento (TCuotaSvein).
Doy por hecho que para dar de alta un socio tengo que hacerlo en 3 pasos que serian:
1 un formulario que me recoja los datos de la tabla TSociosSvein
2 indicarle la situación del nuevo socio y poner fecha
3 elegir la modalidad de cuota etc
Lo he diseñado por encima para ver si este es el funcionamiento que me planteas.
http://filebig.net/files/MUDkZjcgU5
¿Me surgen varias cuestiones las altas según esta planteado en esa bd solo guarda una por socio y debería guardarlas todas verdad? Y las bajas se podría hacer otra estructura idéntica pero para las bajas o la idea es que esa tabla guarde los valores tanto de bajas como altas sean necesarios.
Y la misma cuestión para las cuotas como me comentaste, ya que almacenase todos los valores se podía usar un formulario como el de consulta de cuotas que tengo para saber cuando un usuario estuvo tanto de alta como de baja o quienes están de alta y de baja.
Eso como me lo puedo realizar tipo al ejemplo que me pusiste de consulta de socio en formulario continuo y ese cuyo código es:
Dim miFiltro As String
If IsNull(Me.txtBusca) Then
MsgBox "No ha seleccionado ningún socio", vbInformation, "AVISO"
End If
'Si está en blanco el cuadro de busca, sales sin más
If Nz(Me.txtBusca, "") = "" Then Exit Sub
'Creas el filtro con el valor seleccionado
miFiltro = "[CodigoSocio]=" & Me.txtBusca
'Lo aplicas al formulario
Me.Filter = miFiltro
Me.FilterOn = True
Como puedo añadirle al código si añado un texbox para el año, para que me muestre los pagos del año porque sino... o otro planteamiento más adecuado.
En Tsocios, obviamente quité los campos que ahora van a estar en las dos tablas nuevas.
El funcionamiento que planteas es el correcto, pero puedes simplificarlo si al formulario de socios le añades dos subformularios: uno sobre la tabla TSituacion y otro sobre la tabla TCuota.
Según está estructurada da la BD, en TSituacion registraras todos los movimientos (Altas y bajas) de todos los socios, de forma que tengas un histórico. No te hace falta crear otra tabla igual para las bajas. De hecho, si te fijas en el campo Situacion, se te despliegan las dos opciones (podrías añadirle más, si fueran necesarias)
Lo mismo para cuotas.
Si a ese código le quieres añadir el año como parte del filtro, en tu tabla tienes el campo Año y tu cuadro de texto se llama txtAño, la linea que te cambia es esta:
miFiltro = "[CodigoSocio]=" & Me.txtBusca & " AND Año=" & Me.txtAño
Te dejo un ejemplo de cómo sería el formulario con los subformularios.
Muchas gracias, ¿no me mandaste nada no? es que no lo veo. ¿Si igual seria mejor con subformulario basados cada uno en la tabla correspondiente y me imagino que deberían de ser como hoja de datos no? O podrían ser normales y el código iría en un botón de comando para todo o lo de la situación y cuotas debería actualizarse en cada evento de cada campo después de actualizar... es que tengo esas dudas de como seria el planteamiento ideal.
Me he fijado que mi plantamiento que te mande funciona pero claro no se puede o abría que modificar el código porque si abres solo el FSituacionSven cuando aceptas te sigue abriendo el otro también...
parece que no adjuntó el enlace. Aquí te lo dejo de nuevo: http://filebig.net/files/itXy2hfsZs
Los subformularios puedes hacerlos como más te gusten, en hoja de datos, tabulados, en columnas... eso ya es cuestión personal tuya.
Lo otro que preguntas de botones de comando y código, no lo entiendo...
En el tuyo, tienes que quitarle la linea que te abre el otro formulario.
¿La idea que me planteas me gusta y creo que es efectiva pero en vez de formularios continuos se podrían poner un formulario normal? Ya que solo se va a meter por ejemplo una fecha cuando se da el alta y una cuota etc (me refiero que no hayas más campos solo uno para cada dato), ¿y la pregunta es cuando se le de al botón aceptar cada dato iría a su correspondiente tabla verdad?
Y lo siguiente duda es que según esta planteada la bd habría que hacer otro formulario para FSituacion que es donde se dará de alta y baja tantas veces como sea necesario (y lo mismo para FCuotas, para tantas veces como cambien de cuotas) ya que el que tienes creado ahora con el nombre subFSituacionSvein por su diseño no valdría ya que debería llevar el logo etc..
O hay forma otra forma...
Un saludo
http://filebig.net/files/C7hHVMY6WS
Este es el planteamiento que me refiero según lo que me comentaste haber si es el adecuado y a lo que me planteaste. Por cierto el código que había en el formulario al evento al cargar no iva bien y no vi el error.
Un saludo
Como te comentaba antes, los subformulario los puedes diseñar como mejor te parezca, no hay una forma mejor que otra, depende de tus gustos y lo que quieras mostrar.
Sí, al pulsar Aceptar los datos se guardan en sus tablas correspondientes (de hecho, se te guardarían incluso sin pulsar ese botón, por ejemplo, al cerrar "a las bravas" el formulario o el propio access)
Lo de hacer otro formulario para las altas/bajas y las cuotas, nuevamente dependerá de tus gustos, preferencias y de cómo quieras manejar la aplicación.
Personalmente, tu forma de trabajar no es la que yo usaría, pues me parece duplicar el trabajo. Pero como digo, eso es cuestión de cada uno. Si así te va bien y es lo que necesitas, pues perfecto. Que yo no la usara no quiere decir que no sea válida o peor.
En cuanto al código de Form_Load, lo único que le hice fue modificar la linea antes del Exit, apra que no te sobreescriba el valor si usas el formulario para navegar por los registros (que por lo que planteas entiendo que no lo vas a hacer). Si no te funciona es porque en el formulario o en la tabla al campo codigo socio le tienes asignado un valor predeterminado (concretamente el 0)
Muchas gracias como siempre me gustan tus consejos y de los cuales aprendo mucho ya que tienes más experiencia que yo en planteamientos y todo.
Te decía hacer dos uno como subformulario por el diseño más que nada ya que al cargarlos de forma individual pues para modificar la situación y cuota si cambia etc estuviera más vistoso.
¿También se podría diseñar como estuviera solo y en el evento al cargar del formulario TSocios decirle que las propiedades de ciertos elementos estén o no visibles lo harías así?
Un saludo
Podrías mostrar/ocultar elementos del formulario con la propiedad Visible=True/False, pero creo te ibas a complicar innecesariamente... XD
Buff, explicarte cómo lo haría yo me llevaría mucho tiempo y se te haría demasiado complicado, así que si me lo permites, no lo voy hacer (pero no porque no quiera)
Como breve indicación, te diría que partiría del planteamiento que te mandé (formulario con subformularios continuos) y gestionaría todo desde ese formulario (altas, bajas, cambios de cuotas...). Tendrías que poner el formulario no como entrada de datos, para poder navegar por los registros, y un botón para ir a un nuevo registro (nuevo socio). ASí te evitas tener que duplicar los subformularios.
Si a este formulario "principal" le añades botones para filtrar, ya sería lo más... XD
Mi pregunta es sí lo hago como tu me dices navegando culis registros etc cada vez que cambie la situación o cuota de un socio añadiría un nuevo registro o modificaría el que ya esta por lo tanto no habría histórico.
Si sigues el modelo que te pasé (formulario con subformularios continuos), en los subformularios puedes añadir tantos registros de un mismo socio como quieras, por ejemplo: un alta el dia 10/10, una baja el 30/12, un nuevo alta el 15/03, y así todas las veces que necesites. Con las cuotas, lo mismo.
Haz la prueba en el archivo que te mandé, y verás cómo funciona.
Buenas noches,
Voy hacerlo como tu me indicas creo que es la mejor opción y esta mejor me ahorro mucho trabajo, pero el botón para filtrar la búsqueda del socio me cuesta como todo, creo que como me indicabas la idea seria crear un texbox y un botón filtrar que busque lo que hay en el no?
te adjunto la bd para tu opinión como siempre importante para mí cada día aprendo y me rompo la cabeza xa intentar llegar a lo que me comentas y le doy mil vueltas pero el botón de filtrar me vuelve loco he intentado seguir el modelo de FVerPAgos pero no fui capaz eso si el de nuevo socio si aunque no se si estará bien planteado el código.
http://www.filebig.net/files/KbbeT3Sc4D
Un saludo
No puedo abrir tu archivo, pero el filtro ya lo hiciste antes:
Como puedo realizar que un texbox me de el valor en relación a otros Combos
Lo único es que en vez de aplicarselo al subformulario se lo aplicas al formulario, es decir, en vez de Me.subFrmResultado.Form.Filter=miFiltro, tendrías que poner simplemente Me.Filter=miFiltro. Y con los nombres de los controles correspondientes
Y con esto, doy por finalizada esta pregunta. Si tienes más dudas, abre una nueva... XD
Ok lo abriré en otra pregunta, muchísimas gracias, pero de todas formas lo que he echo y me da error era algo así, el txt es independiente y se llama txtbusca
Dim miFiltro As String
If IsNull(Me.txtBusca) Then
MsgBox "No hay nada que buscar", vbInformation, "AVISO"
End If
If Nz(Me.txtBusca, "") = "" Then Exit Sub
miFiltro = DLookup("Nombre", "TSociosSvein", "[Nombre]='" & Me.txtBusca
Me.Filter = miFiltro
Me.FilterOn = True
Te sobra la comilla simple en la linea líneamiFiltro=..., pues CodigoSocio es un valor numérico:
miFiltro = DLookup("Nombre", "TSociosSvein", "[Nombre]=" & Me.txtBusca)
miFiltro = DLookup("Nombre", "TSociosSvein", "[Nombre]=" & Me.txtBusca, asi me da yo pongo a buscar un nombre y me da el error en esta linea
Si es de tipo texto tienes que ponerle comillas simples:
miFiltro = DLookup("Nombre", "TSociosSvein", "[Nombre]='" & Me.txtBusca & "'"
Léete la ayuda del DLookUp, para aprender cómo buscar los distintos tipos de datos:
http://support.microsoft.com/kb/208786/es
Muchas gracias, me lo voy a leer detenidamente haber si lo saco, ¿por cierto de esta manera como se yo que socios están de alta y baja? ¿Ya qué se acumulan todos los valores si hago una consulta nunca se como están realmente no? Habría que añadir un campo alta/bajo (Si/no) a la la TSocios y en función del código socio y que palabra se use en situación se marque y desmarque ese check o estoy diciendo una barbaridad.
Pero según esta planteado sí yo quiero saber cuantos socios de baja hay actualmente como lo filtro en un subformulario sí por ejemplo un socio se dio de alta y baja varias veces
¿Y para que quieres filtar el subformulario?
Si quieres saber los que están de alta (o baja), tendrás que hacer una consulta de agregados con la tabla situaciones (que te dará la cuenta de las altas o bajas), o con la de Socios y Situaciones si quieres saber quienes son los socios que están de alta o baja, pero esto ya es tema de otra pregunta..
- Compartir respuesta