Crear función usando Trim en todos los controles del formulario

En ocasiones me pasa que me dejo espacios antes y después del texto en los controles del formulario, en cuadros de texto, combos, etc.

Me gustaría poder eliminar esos espacios mediante "TRIM" creando una función en un módulo, que pueda llamar en el evento "al cargar" del formulario o en "al activar registro" para así asegurarme que las cadenas de texto de cualquier control del formulario no tienen espacios delante o detrás.

La función debería abarcar todos los controles del formulario o al menos los controles del form cuyo origen del control es la tabla "Libros". El formulario se llama "FormLibros"

Respuesta
2

Prsonalmente tomaría otro camino, aunque el que apunta Sveinbjorn es correcto, salvo en que hace referencia al Nombre del control y no al contenido del control que es lo que yo interpreto. Dicho esto, haria este Procedimiento, dentro o Fuera del Formulario.

Public Sub QuitaEspaciosIniFin()
Strsql = "select titulo, tomovolumen, coleccion, autor, editorial, tipodocumento, categoria, genero, materia, signatura "
StrSQL = StrSQL & "FROM LIBROS;"
Set Rst = CurrentDb.OpenRecordset(StrSQL, dbOpenDynaset)
'Por pura Rutina, me aseguro que devuelve Registros
If Not Rst.EOF And Not Rst.BOF Then
        Rst.MoveLast
        Rst.MoveFirst
        Do While Not Rst.EOF
                Rst.Edit
                        Rst!TITULO = Trim(Rst!TITULO)
                        Rst!TOMOVOLUMEN = Trim(Rst!TOMOVOLUMEN)
                        Rst!COLECCION = Trim(Rst!COLECCION)
                        Rst!AUTOR = Trim(Rst!AUTOR)
                        Rst!EDITORIAL = Trim(Rst!EDITORIAL)
                        Rst!TIPODOCUMENTO = Trim(Rst!TIPODOCUMENTO)
                        Rst!CATEGORIA = Trim(Rst!CATEGORIA)
                        Rst!GENERO = Trim(Rst!GENERO)
                        Rst!MATERIA = Trim(Rst!MATERIA)
                        Rst!SIGNATURA = Trim(Rst!SIGNATURA)
                        Rst.Update
                Rst.MoveNext
                DoEvents
        Loop
End If
Rst.Close
Set Rst = Nothing
End Sub

Optaria por hacer la llamada en el Evento al Cerrar del Formulario, pero se puede hacer desde un Botón u otro procedimiento.

No resalto porquees Obvio que Modifica toda la Tabla, si es que hay espacios.

No he tenido en cuenta los Campos Fecha,,, Mis saludos >> Jacinto

Hola Jacinto

Sí... interpretas bien, me refería al contenido del control, a que no hubiera espacios antes o después del valor que se inserta en cada control.

No he probado la función (aunque seguro que va genial, como todo lo que me propones) pero quería comentarte una cosa...

Mi interés de hacerlo todo lo que pueda con funciones es para de esa manera poder usar en distintos sitios,  el mismo código.

Pero para eso la función no puede hacer referencia directa a campos o controles de un formulario concreto, porque si no, no me haría falta una función... podría poner el código que me indicas en algún evento del formulario y evitarme de esa manera la función.

Necesitaría una función que no se refiriera directamente a controles del formulario (Titulo, Coleccion, Autor, etc:) , que usara variables, para así poder usarla donde quisiera y luego ya la llamaría en los eventos concretos de cada formulario.

Si tengo una función genérica tan solo tengo que llamarla desde un evento con una simple línea. Imagínate que tuviera que usar esa función para eliminar los espacios de los controles de 5 formularios diferentes con distintos controles... entonces tendría que crear 5 funciones casi iguales, indicando en cada una los nombres de los controles de cada formulario y no sería muy práctico...

Por eso siempre busco funciones construídas con  variables o de otro modo que evite personalizar su código para un form o control concreto, como "DesbloquearControles" o "ControlesNulosEnForm" o "BloqueaBotones" .

Ya me dices si se puede reconstruir la función que me indicas teniendo en cuenta esto que te comento.

Como siempre un saludo y muchísimas gracias por la ayuda

Rafa: Creo que las aclaraciones que te hace Sveinbjorn, son las adecuadas para que la Función que te propone la puedas poner en un Módulo y no hayas de repetirla.

La que yo te propuse si quieres utilizarla para una "Limpieza" general, la pones en un botón porque ciertamente consume recursos de modo innecesario.

Mis saludos >> Jacinto

Hola Jacinto

La verdad es que tu función como bien dices me sirve y mucho para una "limpieza general" ahora que tengo muchos registros y seguro que con espacios en el contenido de los controles.

Luego una vez hecha esa limpieza con tu función, ya podemos usar la función de Sveinbjorn.

Quería saber si en tu función podemos cambiarla y usar una estructura SQL para usar TRIM solo en los campos de la tabla "LIBROS".

Algo así como...

Me.recordsource = "Select TRIM (*) FROM LIBROS

o "Select TRIM (Libros.Titulo) and TRIM (Libros.Autor) y el resto de campos...

o poner directamente el nombre de la consulta en vez de la línea SQL... Ya sé que no vale lo que pongo pero hacerte una idea...

Bueno ya me dices si hay alguna forma mediante SQL de usar TRIM solo en los campos de la tabla "Libros"

Pues Un saludo y gracias por todo

Rafa: Intentando cubrir tu necesidad y a raíz de un comentario constructivo y acertado por supuesto de Sveinbjorn, me he animado a hacer un procedimiento general que quite los espacios Iniciales y Finales de una Tabla, teniendo en cuenta que >>
De entrada tenga en cuenta si el Campo es Autonumérico, que presumo es Entero Largo, Campo Si/No, y dejando la puerta abierta, a que el programador, de acuerdo con la Tabla, excluya de forma explicita 4 campos más. El resultado es el que cito a continuación.

Public Sub QuitaEspaciosIniFin(TablaObjeto As String, Optional ExcluyeCA As String, Optional ExcluyeCB As String, Optional ExcluyeCC As String, Optional ExcluyeCD As String)
Dim BytCampo As Byte
Dim CampoTabla As String
'Jacinto Trillo Jareño 24/02/2016, para una pregunta de Todoexpertos
'Se supone que si hay un Auto Numérico es de tipo dbLong.
'Los Check Box se excluyen para evitar el Error, y además se deben excluir los Campos Calculados
On Error GoTo QuitaEspaciosIniFin_TratamientoErrores
Set Rst = CurrentDb.OpenRecordset(TablaObjeto, dbOpenDynaset)
'Por pura Rutina, me aseguro que devuelve Registros
If Not Rst.EOF And Not Rst.BOF Then
        Rst.MoveLast
        Rst.MoveFirst
        Do While Not Rst.EOF
                For BytCampo = 0 To Rst.Fields.Count - 1
                        CampoTabla = Rst(BytCampo).Name
                        If Rst(BytCampo).Type <> dbLong And Rst(BytCampo).Type <> dbBoolean Then
                                If CampoTabla <> ExcluidoA Then
                                        Rst.Edit
                                                Rst(CampoTabla).Value = Trim(Rst(CampoTabla))
                                        Rst.Update
                                End If
                        End If
                Next BytCampo
                DoEvents
                Rst.MoveNext
        Loop
End If
Rst.Close
Set Rst = Nothing
MsgBox "Se han quitado los espacios Iniciales y Finales de todos los Campos de la Tabla: " & TablaObjeto, vbInformation, "ESPACIOS DE TEXTO SUPRIMIDOS"
QuitaEspaciosIniFin_Salir:
On Error GoTo 0
Exit Sub
QuitaEspaciosIniFin_TratamientoErrores:
MsgBox "Error " & Err & " en Procedimiento.: QuitaEspaciosIniFin de Documento VBA: MdlConsultasYTablas (" & Err.Description & ")", vbCritical + vbOKOnly, "ATENCION"
Resume QuitaEspaciosIniFin_Salir
End Sub  'QuitaEspaciosIniFin(TablaObjeto.................
'Aqui hago el sondeo de si el Campo es ono Calculado
Function EsCampoCalculado(BytCampo As Byte) As Boolean
If Rst.Fields(BytCampo).DataUpdatable = False Then
        EsCampoCalculado = False
Else
        EsCampoCalculado = True
End If
End Function

Este Procedimiento puede llamarse desde cualquier sitio con
Call QuitaEspaciosIniFin(“TablaEsObligada”, “RestoEsOpcional”)

Lo que no me parece adecuado es llamarlo en un Form_Curret, por ejemplo.

En éste caso concreto, yo lo he hecho en un Botón cuyo código es:

Private Sub BtnQuitaEspacios_Click()
Call QuitaEspaciosIniFin("LIBROS", "AñoMasISBN")
End Sub

Supongo que como todo será mejorable

Mis saludos a los dos. Rafa y Sveinbjorn

Jacinto

Las prisas algunas veces son compañeras de los errores y éste es uno de los casos.

He cambiado el Nombre de las variables del Procedimiento y no las he trasladado al código que he henviado.

Public Sub QuitaEspaciosIniFin(TablaObjeto As String, Optional ExcluidoA As String, Optional ExcluidoB As String, Optional ExcluidoC As String, Optional ExcluidoD As String)

Es la línea correcta.

Saludos >> Jacinto

Hola Jacinto

MIL, MIL GRACIAS por tu esfuerzo!!!!!

Funciona de maravilla y en todos los registros, lo que me permitirá hacer una limpieza total de toda la BD.

Ahora sí es una función que puedo aplicar a cualquier formulario o hasta en otras bases de datos. Era lo que necesitaba una función como ésta, global.

--------------------------------------------------------------------------------------------------------------------

Te comento solo un detalle por si se puede rematar la faena

Para hacer pruebas he hecho lo siguiente:

He creado 3 registros en el form, TODOS con espacios en el campo "AUTOR"

Si pulso el botón para eliminar espacios desde el registro 1 me los elimina en todos los registros y funciona perfecto... pero...

1\ He observado que si me voy al registro 2 y desde ahí pulso el botón para quitar los espacios, no me los quita del registro 2 y solo si me voy al registro 3 y vuelvo al 2 se me actualiza el campo "AUTOR" sin espacios.

2\ También he observado que si estoy en el registro 3  y apreto el botón, no me elimina los espacios de ese registro y si voy al registro 2 y vuelvo al 3 sigue sin actualizarse el campo sin espacios. Pero a veces sí funciona y eso es lo raro.

En resumen que si apreto el botón en un registro que no sea el 1, a veces me funciona y en otras no... parece aleatorio no lo entiendo.

Haz la prueba exactamente como te indico (con los 3 registros con espacios en "AUTOR" y verás que a veces haciendo lo mismo me quita los espacios y a veces no.

Ya me dices... Un saludo y de nuevo gracias por la función global.

Rafa: Por lo que observo, esos datos "Creo" que aún no están en la Tabla. Es decir:

En el Formulario estoy visualizando el Registro 2. Modifico el cuadro de Texto AUTOR y Le dejo 10 espacios. Pulso el Botón de quitar espacios y no me hará nada, porque ese dato no ha ido a la Tabla. Voy al Registro 3, Modifico el 3 y pulso el Botón.

Me modificará solo el 2 porque el 3 está en datos del Formulario, no en la Tabla.

Mis saludos >> Jacinto

Hola Jacinto

1\ En parte tienes razón:

Solo si cierro el form y lo vuelvo a abrir o cambio de registro, al apretar el botón me elimina los espacios. (al guardarse ya en tabla)

¿Podría poner alguna línea en el form para que se actualizasen los datos al momento en la tabla sin necesidad de cambiar de registro o cerrar y abrir el form para que así al apretar el boton me eliminara los espacios de ese registro? con "Me.Requery" he probado y nada.

-----------------------------------------------------------------------------------------------------------------------------------

Pero creo que aparte de eso que es cierto hay algo más...

Para comprobarlo:

2\ He dejado en "Autor" espacios en 3 registros y sin pulsar el botón... He cerrado el form para asegurarme que la tabla ya tiene los campos guardados con espacios.

He abierto la tabla y he comprobado que los datos con espacios ya están guardados en el campo "Autor"

He vuelto a abrir el form con los 3 registros con espacios en "Autor" y me he ido al reg. 2 y he pulsado el botón y nada, no actualiza el campo APARENTEMENTE!!!

(He observado que si esperas mucho tiempo, como 1 minuto al final me lo actualiza, después del mensaje)

En cambio si abro el form en el reg 1 y pulso el botón me actualiza enseguida todos los registros y me elimina los espacios.

Aquí no es que no se hayan guardado los cambios en la tabla...

Es que el botón por alguna razón trabaja mucho más lento si lo pulso desde el reg. 2 o posteriores que si lo hago desde el 1.

¿Se podría hacer algo sobre esto para que al margen de en qué reg. estoy el botón trabajara igual?

Saludos

Rafa: He hecho algunos ensaos y no noto esa diferencia de velocidades de poceso.

Además he incluido un Me. Requery en la llamada o sea:

Private Sub BtnQuitaEspacios_Click()
Me.Requery
Call QuitaEspaciosIniFin("LIBROS", "AñoMasISBN")
End Sub

He velto ha hacer pruebas y lógicamente el fenómeno de los registros no guardados desaparece.

Justo he probado dejando espacios en el "AUTOR", de los Registros 2, 3 y 4.

Después he probado con el Campo TITULO y no he tenido problemas.

La verdad es que aparte de poner ese Requery, no se que decirte, salvo enviarte la BD que yo tengo. Lo hago ahora. Saludos >> Jacinto

1 respuesta más de otro experto

Respuesta
2

Te pongo esto de cabeza, sin probarlo, a ver si la vas ajustando a tus necesidades:

Public Sub subQuitaEspacios(elForm as Form)

Dim ctl as Control

For Each ctl in elForm.Controls

If ctl.ControlType=acTextBox Then elForm.Controls(ctl.Name)=Trim(elForm.Controls(ctl.Name))

Next ctl

End Sub

Y lo llamas así:

Private Sub Form_Load()

subQuitaEspacios Me

End Sub

Se me olvidó un detalle: si tienes un campo autonumérico, tienes que excluirlo para que no te de error, o ignorar ese error con un control de errores.

Hola Sveinbjorn

Sí... Tengo un campo  autonumérico "IDLIBROS" y me da error...

¿Podrías indicarme cómo excluirlo?

También me marca como error la línea...

If ctl.ControlType=acTextBox Then 

elForm.Controls(ctl.Name)=Trim(elForm.Controls(ctl.Name))

Y por último he visto que lo que me indicas solo me funciona en el registro 1, solo me elimina los espacios de los controles en el registro 1 y no en los demás registros.

Ya me dices

Un saludo

Un par de aclaraciones, deprofundis:

1º/ El código funciona perfectamente, no da error en al linea que dices, a menos que tu hayas escrito algo mal en tu BD (se me ocurre que lo hayas puesto en dos lineas en vez de una. http://www.filebig.net/files/CbVhEiK8SC 

Antes de abrir el formulario, fíjate que los campos de la tabla tienen espacios y al abrirlo se eliminan.

2º/ Hace lo que pides: "La función debería abarcar todos los controles del formulario o al menos los controles del form cuyo origen del control es la tabla "Libros""

Si lo pones en "Al cargar", te elimina los espacios en los textbox del registro que se carga (el primero, el último... el que sea)

Si lo pones en "al activar registro", te lo hará cada vez que cambies de registro.

Otra cosa es lo que comentas aquí: "solo me funciona en el registro 1, solo me elimina los espacios de los controles en el registro 1 y no en los demás registros."

Si quieres que te revise todos los registros de la tabla, tienes que trabajar sobre la tabla, no sobre el formulario, como la solución que te propone Jacinto.

3º/ Para no tener en cuenta el campo ID, puedes añadirle esto (forma obvia):

Public Sub subQuitaEspacios(elForm As Form)
Dim ctl As Control
For Each ctl In elForm.Controls
    If ctl.ControlType = acTextBox And ctl.Name <> "ID" Then elForm.Controls(ctl.Name) = Trim(elForm.Controls(ctl.Name))
Next ctl
End Sub

Si quieres controlar otros tipos, añades sus constantes al If (acComboBox, acListBox)

4º/ Relacionado con el punto 2, hacer la comprobación en toda la tabla cada vez que cargas un registro o te mueves por ellos es una pérdida de recursos. Tendría sentido hacerlo una vez para revisar los datos existentes, pero en las siguientes sólo es necesario comprobar los registros nuevos.

Esto quiere decir que el evento en el que colocar el procedimiento debe ser otro ("antes de actualizar", "al guardar"...) Si tienes un botón para guardar, ese sería el lugar adecuado.

La "ventaja" de mi propuesta es precisamente que la puedes usar con cualquier formulario sin tener que modificarla, como comenta Jacinto, al no estar haciendo referencia directa a los nombres de los objetos.

Hola Sveinbjorn

Tienes razón en Todo!!!

Tu función va genial y ahora estoy seguro... porque me bajé tu ejemplo y funciona perfectamente, perdona.

Pero algo debe haber mal en mi BD porque cuando abro el formulario me salta este mensaje

y luego me subraya esta línea

Se te ocurre qué puedo tener mal para que me salte este mensaje y me subraye la línea...

Ya me comentas y muchas gracias por la ayuda.

Ese error te lo da al intentar editar el autonumérico. En la bd de ejemplo y en el código de la segunda respuesta (punto 3), tienes una forma de evitarlo.

Hola Sveinbjorn

Como bien dices es 100% por culpa del campo "ID" que es autonumérico porque para hacer la prueba lo he pasado a numérico y ya no me da error...

Una vez sé esto lo que no comprendo es por qué si pongo el código como me dices (segunda respuesta punto 3) justamente para evitar el error, me sigue dando error.

Yo pongo lo que me dices para evitar el error que me genera el "ID" autonumérico:

Public Sub subQuitaEspacios(elForm As Form)
Dim ctl As Control
For Each ctl In elForm.Controls
    If ctl.ControlType = acTextBox And ctl.Name <> "ID" Then elForm.Controls(ctl.Name) = Trim(elForm.Controls(ctl.Name))
Next ctl
End Sub

Pero me sigue saltando el error... "no se puede asignar un valor a este objeto". El caso es que tu código está perfecto.

¿Podríamos ignorar el error que produce el "ID" autonumérico creando un control de errores...? A ver si así evito el problema.

Ya me dices cómo quedaría el control de errores... y con eso cierro el tema y como siempre muy agradecido.

Un saludo

A ver, primero dices que mi BD te funciona (tiene un campo autonumérico llamado "ID"), y luego que el mismo código en la tuya no funciona con tu cmapo autonumérico. La pregunta obvia es ¿tu campo se llama ID? Y si no es así, ¿Modificaste el código para que se adapte a tu BD? A mi me da que no.

Con control de errores, que a estas alturas ya deberías ser capaz de hacerlo tu mismo, sería así:

Public Sub subQuitaEspacios(elForm As Form)
On Error Goto sol_err
Dim ctl As Control
For Each ctl In elForm.Controls
    If ctl.ControlType = acTextBox Then elForm.Controls(ctl.Name) = Trim(elForm.Controls(ctl.Name))
Next ctl
Salida:
Exit Sub
sol_err:
If Err.Number=2448 Then
resume next
Else
Msgbox "Se ha producido el error " & Err.Number & ": " & Err.Description, vbInformation
End If
End Sub

Hola Sveinbjorn

Dame un voto de confianza :) :)

Sigo diciendo lo mismo:

Tu ejemplo me funciona perfectamente...

Pero el mismo código en mi BD, salta el error 2448  y me subraya en amarillo parte de esta línea:

If ctl.ControlType = acTextBox And ctl.Name <> "ID" Then elForm.Controls(ctl.Name) = Trim(elForm.Controls(ctl.Name))

desde   "... elForm.Controls(ctl.Name) = Trim(elForm.Controls(ctl.Name))"

... y SÍ... he modificado el código que me mandas con respecto a mi campo autonumérico. En mi BD el campo se llama "IDLIBRO" y así lo he modificado en la función que me propones.

Public Sub subQuitaEspacios(elForm As Form)
Dim ctl As Control
For Each ctl In elForm.Controls
    If ctl.ControlType = acTextBox And ctl.Name <> "IDLIBRO" Then elForm.Controls(ctl.Name) = Trim(elForm.Controls(ctl.Name))
Next ctl
End Sub

Lo de arriba es lo que he puesto... como ves, he cambiado tu "ID" por el nombre que yo tengo en el campo autonumérico que es "IDLIBRO" pero sigue dándome error.

Debe haber algo incompatible con ese código en mi BD. En fin ya lo encontraré

Un saludo y gracias por la ayuda

El nombre que tienes que poner es el que tengas en el formulario, no en la tabla, que no tienen por qué coincidir.

Verificado esto, que supongo que sí, igual el error no te lo da el autonumérico.

¿Tendrás algún cuadro de texto cuyo origen de control sea una expresión o algún cuadro que tenga como origen un campo calculado en al tabla?

Si es así (he de suponer que sí, pues sería la única explicación lógica), has de añadir esos campos al If (o usar la versión con el control de errores)

GRACIAS!!! POR FIN encontramos el problema!!

En un principio para el autonumérico tenía distinto nombre en la tabla y en el formulario, en uno se llamaba "IDLIBRO" y en otro "TboxIDLIBRO" pero eso ya lo tuve en cuenta y puse finalmente en las pruebas para tu código "IDLIBRO" tanto en el campo autonumérico de la tabla como en el nombre del control del formulario. En los dos casos en las pruebas lo renombré como "IDLIBRO" para no tener este problema. Por tanto el problema como intuías finalmente no estaba en el autonumérico...

Lo que sí que tengo es un cuadro de texto cuyo origen del control es una expresión.

El cuadro de texto se llama TxtRegActivos.

¿Cómo me quedaría el código si tengo que meter este cuadro de texto en el IF...? Tal vez así:

Public Sub subQuitaEspacios(elForm As Form)
Dim ctl As Control
For Each ctl In elForm.Controls
    If ctl.ControlType = acTextBox And ctl.Name <> "TboxIDLIBRO" And ctl.Name <> "TxtRegActivos" Then elForm.Controls(ctl.Name) = Trim(elForm.Controls(ctl.Name))
Next ctl
End Sub

Supongo que como siempre no he acertado... Ya me dices cómo añadir al código el nombre del control cuando puedas.

Un saludo y gracias por no abandonar :-)

Usa la función que tiene el control de errores, te será más fácil y además "portable" para cualquier formulario de cualquier bd.

Yo anidaría los IFs:

If ctl.ControlType = acTextBox Then

 If ctl.Name <> "TboxIDLIBRO" OR ctl.Name <> "TxtRegActivos" Then

elForm.Controls(ctl.Name) = Trim(elForm.Controls(ctl.Name))

End If

End If

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas