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
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
- Compartir respuesta
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.
- Compartir respuesta