VBA ACCESS Como actualizar los labels de un form sin usar Requery, Recal o Refresh

Tengo un subForm que recibe datos de una tabla. Cada cierto tiempo modifico los valores de la tabla con una consulta de actualización lanzada por un Timer cada minuto. Quisiera refrescar los valores del form provenientes de la tabla sin usar Requery, Recal o Refresh para evitar el parpadeo que realiza el form al repintar todo. Hay alguna forma de actualizar los valores sin repintar.

1 respuesta

Respuesta
2

La forma más adecuada para evitar el parpadeo de pantalla al operar con registros de un formulario (o subformulario) es la que te indicaba Icue en la otra pregunta sobre este tema (ACCESS VBA Actualizar un txt de un formulario ejecutando el Timer), es decir, usar Application.Echo False/True, para desactivalo/activarlo.

Por lo que comentas, y según yo lo entiendo, el parpadeo no tiene nada que ver con que hagas un requery, refresh... al subformulario, sino con las reglas que tienes en el formato condicional, que se aplican una vez los datos están "recargados". Y eso no lo puedes evitar con Echo, al menos que yo sepa, y tras las pruebas que he realizado.

Probando cosas, en un formulario continuo con muchos registros y con varias reglas de formato condicional, y además de usar lo de Application. Echo en un cuadro combinado para recargar los datos del formulario filtrados, logro una reducción o eliminación del parpadeo que provoca el formato condicional, si en vez de usar el formato condicional uso el evento "al pintar" de la sección detalle del formulario para darle el formato al campo.

Es decir, en vez de configurar un formato condicional así:

Pongo este evento:

Private Sub Detalle_Paint()
Select Case Me.Distancia
    Case Is < 5
        Me.Distancia.BackColor = vbRed
    Case Is > 11
        Me.Distancia.BackColor = vbGreen
    Case Else
        Me.Distancia.BackColor = vbYellow
End Select
End Sub

con lo que consigo el mismo efecto visual en el formulario.

Además, en el cuadro combinado, pongo:

Private Sub cboFiltroRecorrido_AfterUpdate()
Application.Echo False
' Operaciones varias para filtrar los registros que no vienen al caso
Application.Echo True
End Sub

A ver si te sirve esta alternativa.


Si no, para "actualizar" los registros sin usar requery ni similares, lo único que se me ocurre (y es una solución que personalmente no me gusta nada) es que hagas un recorrido uno a uno de los registros del subformulario y vayas modificando uno a uno los cuadros de texto, lo que es un proceso más largo y que provocará más parpadeos (que debieras poder quitar con application. Echo). La idea sería hacer una cosa así, teniendo el cursor en el primer registro del subformulario:

For i=1 to Me.Recordset.Recordcount 
'aquí vas dando a cada cuadro de texto el valor
Me.Control1=...
Me.Control2=...
DoCmd.GoToRecord , , acNext
next i

Esto te exigirá tener una forma de saber qué valor darle a cada registro...

Un saludo.


Muchas gracias Sveinbjorn El Rojo,

He optado por sustituir el formato condicional por pintar el fondo de  cada etiqueta. He realizado este procedimiento para dar color a las etiquetas. Para que una etiqueta  en un formulario continuo  cambie de color en cada linea según la condición que cumpla creo que esto hay que hacerlo al cargar los datos del formularios desde vba.

Dim Gris As Long, Verde As Long, Rosa As Long, Amarillo As Long, Azul As Long
Dim Ref As TextBox, Turno As TextBox

Set Ref = Form_PlanSemSub.Ref
Set Turno = Form_PlanSemSub.Ref
'Colores
Gris = RGB(205, 205, 255)
Verde = RGB(141, 195, 5)
Rosa = RGB(255, 153, 204)
Amarillo = RGB(255, 255, 102)
Azul = RGB(87, 143, 255)

'Pintamos el fondo de las etiquetas según condición que cumplan
If IsNull(Ref.Value) Then Ref.BackColor = Gris
If Turno.Value = "Tarde" Then Ref.BackColor = Rosa
If Turno.Value = "Noche" Then Ref.BackColor = Amarillo
If Turno.Value = "Mañana" Then Ref.BackColor = Azul

He adjuntado un procedimiento que le pasa los datos al formulario, pero no se como debería introducir el procedimiento que condiciona el color de las etiquetas.  

Sub rs_Plan()
Dim Cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim Sql As String

Sql = "SELECT * From Modulo_Plan"& _
"ORDER BY Id, Ref;"

Set Cn = CurrentProject.AccessConnection
Set rs = New ADODB.Recordset
With rs
   Set .ActiveConnection = Cn
   .Source = Sql 'El form carga datos desde aquí
   .LockType = adLockOptimistic
   .CursorType = adOpenKeyset
   .Open
End With
'Set the form's Recordset property to the ADO recordset
Set Form_Sub_Plan.Recordset = rs
Set rs = Nothing
Set Cn = Nothing

End Sub

Para que un control cambie de color en un formulario continuo, no te sirve el evento "al cargar", ni "al activar registro". Como te decía en mi respuesta, el evento a usar es "al pintar" de la sección del formulario donde tengas el control. Y te lo dije precisamente porque lo probé previamente y funciona exactamente igual que el formato condicional.

En cuanto a los códigos que pones, me parece mucha complicación para hacer algo relativamente sencillo:

Empezando por el segundo procedimiento que pones, si haces simplemente:

Me.RecordSource =  "SELECT * From Modulo_Plan ORDER BY Id, Ref;"

ya tienes esa consulta como origen de datos del formulario...

En cuanto al primero, hacer:

Dim Gris As Long
Gris = RGB(205, 205, 255)
... Ref. BackColor = Gris

me parece escribir código por escribir... Como los colores no van a variar nunca en la ejecución del código, podrías haber puesto directamente:

... Ref. BackColor = RGB(205, 205, 255) 'Gris

y poner comentarios para saber qué color es cada RGB(), o usar constantes y aún así escribir menos código del que tienes:

Const Gris As Long = RGB(205, 205, 255)
... Ref. BackColor = Gris

Tampoco le veo la necesidad de referenciar los formularios y controles, pero ahí no te puedo dar una orientación exacta porque desconozco cómo tienes montada tu BD. Pero suponiendo que Ref sea el cuadro de texto a colorear del subformulario y Turno sea un cuadro de texto del formulario principal (donde tienes el subformulario), el evento "al pintar" de la sección Detalle del subformulario (suponiendo que están ahí los cuadros de texto como sería de esperar) te quedaría:

Private Sub Detalle_Paint()
If IsNull(Me.Ref) Then Me.Ref.BackColor = RGB(205, 205, 255)  'Gris
If Me.Parent.Turno= "Tarde" Then Me.Ref.BackColor = RGB(255, 153, 204)  'Rosa
If Me.Parent.Turno= "Noche" Then Me.Ref.BackColor = RGB(255, 255, 102)  'Amarillo
If Me.Parent.Turno= "Mañana" Then Me.Ref.BackColor = RGB(87, 143, 255)   'Azul
End Sub

y te pintará de colores el cuadro de texto "Ref" en función del valor de "Turno" igual que lo hace el formato condicional

FUNCIONA PERFECTAMENTE  Y GRACIAS POR MEJORAR MI FORMA DE PROGRAMAR 


Muchas gracias por la ayuda :D

Entiendo que lo del parpadeo también quedó solucionado, ¿no?

Has aportado una solución muy importante, porque de esta forma se elimina el parpadeo que provocan los formatos condicionales al actualizar los valores de las etiquetas. Deja el Timer libre para poder ejecutar procedimientos sin que estos se visualicen gráficamente dejando la pantalla limpia 

Genial! Y tanto tú como yo aprendimos la forma de hacer lo mismo que el formato condicional por código...

Hola!! 
he pasado todo el formato condicional a código dentro del evento “ al pintar” y con los sub formularios continuos sigue apreciándose cómo la imagen no queda congelada y carga. Ha mejorado mucho a la hora de  cargar al no  usar el formato condicional,  pero se sigue apreciando que se ha ejecutado un procedimiento porque se aprecia el parpadeo en el subformulario. Con un solo formulario no se nota nada, pero con el subformulario continuo si. He probado de aplicar el método 

Application. echo false 

recalc

Application. echo True

y no hace nada. Pero si no habilitó el True y comentó la parte false  la pantalla queda completamente congelada y no deja trabajar, lo que quiere decir que este metido está actuando pero no de la forma que querría. 
gracias 

Partiendo del hecho de que desconozco casi completamente tu BD (solo vi una imagen de un subformulario), cómo funciona, qué proceso es el que ejecutas para rellenar esos cuadros de texto, cuándo lo ejecutas... poco te puedo añadir a lo que comentado...

Lo que sí decirte que si desactivas el refresco de pantalla (con echo false), y no lo vuelves a activar (en algún momento), Access se queda "congelado" en el instante en que lo desactivas, por eso no te deja hacer nada...

Se me ocurre que juegues con el evento Timer para activar el refresco, algo así:

a) en algún punto del tu código, previo a que se hagan los cálculos o la recarga del subformulario (no sé exactamente lo que haces), pones lo de Application.Echo False y añades un Me.TimerInterval=500 (1000 = 1 segundo, o el tiempo que consideres oportuno para que le de tiempo a ejecutar tanto los procesos de actualización como de darle formato a los cuadros)

b) luego en el evento Timer del formulario, activas de nuevo el refresco de pantalla (Application.Echo True) y desactivas el Timer (Me.TimerInterval=0)

Pero esto tendrás que probarlo, ya que igual tienes que hacerle lo del timer a alguno de los subformularios y no al formulario principal...

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas