Establecer un mismo valor a varios objetos

Una duda que siempre he tenido:

¿Hay alguna forma de poder simplificar un proceso donde todos los objetos similares pueda aplicarse un mismo valor?
Por ejemplo:
Teniendo una serie de casillas de verificación, a través del botón "Invertir selección" poder, de una sola vez y un análisis muy simple activar las casillas desactivadas y desactivar las activas.
Lo que hice es, una por una, mediante un If invertir el estado:

if chkVALOR1 = true then
   chkVALOR1 = false
else
   chkVALOR1 = true
End if

Pero eso es uno por uno. ¿Hay alguna forma de hacerlo con menos código?

2 Respuestas

Respuesta
2

Sasha: Si quieres sondearlas todas y ponerlas a True o False, puedes hacer.

Dim Ctrl As Access.Control
For Each Ctrl In Me.controls
    If Ctrl.ControlType = acCheckBox Then
        If Ctrl.Value = True Then
            ctrl.Value = False
        Else
            ctrl.Value = True
        End If
     End If
Next Ctrl

Ese código te invertirá los valores Actuales.

Si lo que quieres es desactivarlos todos.

Dim Ctrl As Access.Control
For Each Ctrl In Me.controls
    If Ctrl.ControlType = acCheckBox Then
        Ctrl.Value = False
    End If
Next Ctrl

Y el contrario para activarlos todos. No lo he probado pero no debes tener dificultades y si fuera así me comentas. Recuerda además que en lugar de True pudes poner -1 y en lugar de False puedes poner 0(Cero). Mis saludos >> jacinto

¡Excelente! Me ahorró cientos y cientos de líneas.
Ahora, ¿hay alguna forma de hacerlo con ciertas casillas?
El tema concreto es así:
Hay usuarios que pueden cargar datos otros que pueden editar, otros consultar y otros pueden hacerlo todo. El Código le 'permite' o no a acceder a cosas que no deberían.
Por ello, si diferenciara a las casillas de permisos a editores con una E (chkELibro, chkEEditorial, etc.) y a los que pueden cargar con una N (chkNLibro, chkNEditorial, etc.), ¿habría alguna forma que el código se adapte a los que cumplan esa condición?
Por ejemplo, si el Usuario tiene privilegio 3 (Editor), que sólo se accione sobre las casillas que contengan chkE y no sobre las chkN?
No sé si se ha entendido.
Igual, el código que me has pasado me sirve para otros forms donde me ahorro líneas y líneas de código.

Por supuesto Sasha que puedes discriminar.

Donde hacemos el sondeo del If >> Por Ejemplo

If Ctrl.ControlType = acCheckBox Then lo conviertes en
If Ctrl.ControlType = acCheckBox And Left(Ctrl.Name,4) = "chkE" Then
'Aquí lo que quieras que haga

Tambiín puedes hacerlo con una Variable. Ejemplo >>

Dim IzqCheck As String

IzqCheck = Left(Ctrl.Name,4), para ahorrarte cada vez el cálculo.

Mis saludos >> Jacinto

Estoy en proceso de limpieza del código y ahora surge otro problema:
Si el usuario es, por ejemplo, editor (chkE), establezco .enabled = false en las chkN.
¿Cómo hago para hacerlo mediante código en un solo paso?

En resumen:
A los usuarios nivel 2 (que pueden cargar):

  • Enabled = true en todo.

A los usuarios nivel 3 (editores):

  • chkN .enabled = false
  • chkE .enabled = true

Y a los usuarios nivel 4 (sólo pueden consultar)

  • chkN y chkE en.enabled = false

EL código para cada tipo de usuario posible quedó así:

If LVL = 1 Then
    For Each Ctrl In Me.Controls
        If Ctrl.ControlType = acCheckBox Then
            Ctrl.Enabled = False
            Ctrl.Value = True
        End If
    Next Ctrl
ElseIf LVL = 2 Then
    For Each Ctrl In Me.Controls
        If Ctrl.ControlType = acCheckBox Then
            Ctrl.Enabled = True
        End If
    Next Ctrl
ElseIf LVL = 3 Then
    For Each Ctrl In Me.Controls
        If Ctrl.ControlType = acCheckBox And Left(Ctrl.Name, 4) = "chkN" Then
            Ctrl.Enabled = False
        End If
        If Ctrl.ControlType = acCheckBox And Left(Ctrl.Name, 4) = "chkE" And Left(Ctrl.Name, 4) = "chkE" Then
            Ctrl.Enabled = True
        End If
    Next Ctrl
ElseIf LVL = 4 Then
    For Each Ctrl In Me.Controls
        If Ctrl.ControlType = acCheckBox And Left(Ctrl.Name, 4) = "chkN" And Left(Ctrl.Name, 4) = "chkE" Then
            Ctrl.Enabled = False
        End If
        If Ctrl.ControlType = acCheckBox And Left(Ctrl.Name, 4) = "chkC" Then
            Ctrl.Enabled = False
        End If
    Next Ctrl
Else
    For Each Ctrl In Me.Controls
        If Ctrl.ControlType = acCheckBox Then
            Ctrl.Enabled = False
            Ctrl.Value = False
        End If
    Next Ctrl
End If

Pero al abrir el formulario me da error como si intentara guardar el registro con un campo obligatorio en blanco.

Sasha: Con ésto último me has confundido un poco.

Por tanto voy a Suponer que el Nivel de usuario ya lo tienes en alguna variable y que lo puedes llamar desde cualquier sitio.

Supondré también que el Nombre de esa variable es >> NivelUser

Siendo así el limitar el Acceso lo puedes hacer en el Evento Form_Current() mas o menos así

Private Sub Form_Current()
Dim Ctrl As Access.Control
Dim IzqControl As String
For Each Ctrl In Me.Controls
If Ctrl.ControlType = acCheckBox Then
IzqControl = Left(Ctrl.Name,4)
Select Case NivelUser.Value
    Case 2
       Ctrl.Locked = False
    Case 3
        If IzqControl = "ChkN" Then
            Ctrl.Locked = True
        ElseIf IzqControl = "ChkE" Then 
            Ctrl.Locked = False   
        Else
        End If
     Case 4
        Ctrl.Locked = TRue
End Select
End If
End Sub

 Observa que uso Locked en lugar de Enabled. Adapta los Niveles a lo que realmente necesites. Mis saludos >> Jacinto

¡Gracias!
En realidad fue un error mío en el Código. Usé el BackUp y volví a comenzar y el resultado fue contundente: ¡FUNCIONÓ!

Me ha surgido un problema que me da dolores de cabeza:

For Each CTRL In Me.Controls
        If CTRL.ControlType = acCheckBox And Left(CTRL.Name, 4) = "chkN" andLeft(CTRL.Name, 4) = "chkE" andLeft(CTRL.Name, 4) = "chkC" Then
            CTRL.Value = True
            CTRL.Enabled = False
        End If
    Next CTRL

Me deja los checkboxes activos.
Y si cambio los AND por OR me dice:

"No se puede agregar o cambiar el registro porque se necesita un registro relacionado en la tabla 'US_NIVEL'."
La tabla que menciona tiene dos campos: NIVEL y DETALLE
En nivel va el número que se asigna al usuario (1 Administrador [que por caso es el que da el problema], 2 Cargador, 3 Editor, etc.) y el campor DETALLE simplemente tiene el nombre del nivel de usuario.
Te hago llegar un archivo de ejemplo para que veas qué hay que corregir.
https://mega.nz/#!AYpV2Twb!HAHiGpP7yWtT8Z6CD2UcQZcDwKIuON0T5T21OqaTh2s 

Sasha: Intento bajarme el archivo del enlace que has facilitado y me dice que no está disponible.

Ya me comentarás >> Jacinto

No se que ha pasado con el archivo pues no está donde lo dejé... De todas formas por alguna misteriosa razón ahora funcionó.

Sólo dime, ¿el código que pasé es correcto?

For Each CTRL In Me.Controls
    If CTRL.ControlType = acCheckBox And Left(CTRL.Name, 4) = "chkN" And Left(CTRL.Name, 4) = "chkE" And Left(CTRL.Name, 4) = "chkC" Then
        CTRL.Value = True
        CTRL.Enabled = False
    End If
Next CTRL

¿O el segundo y tercer AND debería ser OR?
Porque me ha funcionado y no me ha funcionado con ambos. Por eso no sé cuál es correcto en definitiva.
En el ejemplo había cambiado el código a:

For Each CTRL In Me.Controls
    If CTRL.ControlType = acCheckBox And Left(CTRL.Name, 4) = "chkN" Or Left(CTRL.Name, 4) = "chkE" Or Left(CTRL.Name, 4) = "chkC" Then
        CTRL.Value = True
        CTRL.Enabled = False
    End If
Next CTRL

Y me había arrojado el error: "No se puede agregar o cambiar el registro porque se necesita un registro relacionado en la tabla 'US_NIVEL'."

Sasha: Por lo que intuyo y aunque ocurra en esas líneas, el error viene de como tienes hecha la estructura. Supongo que al cambiar valores hay un conflicto de relaciones de Tablas, pero voy un poco a ciegas.

Lo del uso de los operadores AND y OR dependrá en cada caso de lo que esperes que haga el código si se cumplen unas condiciones u otras de Sondeo.

Ejemplo: Si buscas personas nacidas en el año 1980 "Y" o sea (AND) el Nombre se llame Josefa te devolverá "SOLO" las Josefa Nacidas en el 1980 .

Pero si pones 1980 O (Or) Josefa te devolverá "TODOS" los nacimientos de 1980 y "TODAS" las Josefa hayan nacido en 1980 o en 2010, o ...

Como a veces extenderse sobre lo que ya hay escrito es una repetición innecesaria, te facililito el enlace de Microsoft que trata el tema nuy breve y acertado de estos y otros Operadores.

https://support.office.com/es-es/article/Tabla-de-operadores-e1bc04d5-8b76-429f-a252-e9223117d6bd 

Mis saludos >> Jacinto

Gracias por la información. Sé medianamente como manejar los AND y OR. El tema es que no sé cómo funciona el código...

CTRL.ControlType = acCheckBox And Left(CTRL.Name, 4) = "chkN" And Left(CTRL.Name, 4) = "chkE" And Left(CTRL.Name, 4) = "chkC"

En este caso cómo 'filtra' el resultado...
Yo lo interpreto de una manera que es difícil de expresar sin caer en una redundancia. Trataré de que se vea la diferencia para que se pueda aclarar mi duda:
1) EL CTRL tiene que ser un CHECKBOX también llamarse CHKN también llamarse CHKE para que se cumpla la condición.
-o-
2) El CTRL tiene que ser un CHECKBOX también llamarse CHKN o llamarse CHKE para cumplir la condición.
Si interpreto bien sería que en el caso 2 sería un objeto CHECKBOX llamado CHKN o puede ser cualquier objeto llamado CHKE. ¿Es correcto?
Cualquiera sea el caso, ¿cómo hago para que sea siempre un CHKBOX que se llame X, Y o Z según necesite? A veces serán X e Y y no Z, otras X pero no Y y Z... ¿Se entiende mi duda?

Sasha: Lo que comentas es correcto.

Caso 1.- Un Control no se puede llamar "el mismo" de dos maneras. O sea que esa condición no se cumplirá nunca, según yo lo veo.

Caso 2.- Para cambiar el estado de uno o varios controles, siempre necesitarás una o más condiciones previas. Salvo que des una instrucción concreta. Ejemplo Me.Chk01 = -1

Y vamos al final de tu Texto:

Remitiendome a la estructura "Base", del código que te recomendé>>

Private Sub Form_Current()
Dim Ctrl As Access.Control
Dim IzqControl As String
For Each Ctrl In Me.Controls
If Ctrl.ControlType = acCheckBox Then
IzqControl = Left(Ctrl.Name,4)
Select Case NivelUser.Value
    Case 2
       Ctrl.Locked = False
    Case 3
        If IzqControl = "ChkN" Then
            Ctrl.Locked = True
        ElseIf IzqControl = "ChkE" Then 
            Ctrl.Locked = False   
        Else
        End If
     Case 4
        Ctrl.Locked = TRue
End Select
End If
End Sub

Puedes hacer las combinaciones que quieras o mejor dicho que necesites.

Ejemplo >> Teniendo el número (o el texto), del usuario lo puedes usar en el Select.

Si es que estás atascado y en éste caso yo tampoco sepa ver el alcance del tema, mi sugerencia es:

a.-Pon tu BD en un enlace y con datos inventados aquí con el fin de que alguna otra persona o yo mismo, te podamos ayudar.

B.- Si por alguna razón no quieres tu BD de forma Pública, y quieres mandarmela a [email protected] veo como echarte una mano.

Mis saludos >> Jacinto

Respuesta
2

Otra forma de invertir los checkboxes, con menos código, sería:

Dim Ctrl As Access.Control
For Each Ctrl In Me.controls
    If Ctrl.ControlType = acCheckBox Then Ctrl.Value=Not Nz(Ctrl.Value,0)
Next Ctrl

El Nz() se usa para darle un valor falso, porque si el checkbox aún no tomó el valor verdadero o falso, el código no funciona.

Comprendo.
No sé como funciona Nz más allá de lo que expresas por lo que haré la preguntonta del día:
¿Si el comando es Nz(Ctrl.Value,1) pasa a ser verdadero?

No, como te comenta Jacinto en su primera respuesta, verdadero sería -1.

La función Nz se usa para dar un valor a una variable u objeto cuando éste es nulo.

Los checkbox, salvo que hayas tenido la previsión de darles un valor predeterminado (verdadero o falso), por defecto están en un "tercer estado" en que no son ni verdadero ni falso. Por eso si omites esa función y pones simplemente: Ctrl.Value=Not Ctrl.Value el código no funciona.

Y una cosa más, te recomiendo que uses la ayuda de Access (pulsando F1) pues para resolver estas pequeñas dudas, es lo más rápido, además de que es buena y con ejemplos explicados.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas