martes, 20 de abril de 2010

SELECT CASE anidado.

En una ocasión expliqué mediante un ejemplo sencillo como emplear la instrucción SELECT CASE, hoy complicaremos un poco más esta instrucción utilizándola en varias ocasiones para anidar diferentes condicionales sobre una única función.
El problema planteado es el siguiente:

...en una base de datos de personas, el objetivo es que Excel diga la clasificacion del porcentaje de grasa de una persona, el cual se obtiene por un numero que da una balanza.
El problema es que son muchas condicionales!
Si es mujer de 18-39 años: 0-21 bajo en grasa;22-33 normal;34-39 alto en grasa;más de 39 obesidad.
Si es mujer de 40-59 años:0-23 bajo en grasa;24-34 normal;35-40 alto en grasa; más de 40 obesidad.
Si es mujer de 60-69 años: 0-24 bajo en grasa;25-36 normal;37-42 alto en grasa; más de 42 obesidad.
Si es hombre de 18-39 años: 0-8 bajo en grasa;9-20 normal;21-25 alto en grasa;más de 25 obesidad
Si es hombre de 40-59 años: 0-11 bajo en grasa;12-22 normal;23-28 alto en grasa;màs de 28 obesidad
Si es hombre de 60-99 años: 0-13 bajo en grasa;13-25 saludable;26-30 alto en grasa; más de 30 obesidad.


Si bien podríamos optar por desarrollar la fórmula anidando repetidamente la función SI condicional, es cierto que sólo lo podríamos implementar con versiones superiores a Excel 2003, ya que en esta o anteriores nuesto máximo de anidaciones era de siete...

Recordemos que para crear una funcíon personalizada o UDF debemos acceder al Editor de VBA presionando Alt+F11, y ya dentro del Editor insertar un modulo (Menú Insertar > Modulo), haciendo doble clic en el módulo copiaremos el siguiente código:

'creamos una función con tres variables - Sexo, Edad y % grasa
Public Function Grasa1(sexo, edad, Porcgra)
Select Case sexo
'definimos categorías para mujeres
Case Is = "M"
Select Case edad
Case 18 To 39
Select Case Porcgra
Case 0 To 21: Grasa1 = "bajo en grasa"
Case 22 To 33: Grasa1 = "normal en grasa"
Case 34 To 39: Grasa1 = "alto en grasa"
Case Is > 39: Grasa1 = "obesidad"
End Select
Case 40 To 59
Select Case Porcgra
Case 0 To 23: Grasa1 = "bajo en grasa"
Case 24 To 34: Grasa1 = "normal en grasa"
Case 35 To 40: Grasa1 = "alto en grasa"
Case Is > 40: Grasa1 = "obesidad"
End Select
Case 60 To 99
Select Case Porcgra
Case 0 To 24: Grasa1 = "bajo en grasa"
Case 25 To 36: Grasa1 = "normal en grasa"
Case 37 To 42: Grasa1 = "alto en grasa"
Case Is > 42: Grasa1 = "obesidad"
End Select
End Select
'lo mismo para hombres
Case Is = "H"
Select Case edad
Case 18 To 39
Select Case Porcgra
Case 0 To 8: Grasa1 = "bajo en grasa"
Case 9 To 20: Grasa1 = "normal en grasa"
Case 21 To 25: Grasa1 = "alto en grasa"
Case Is > 25: Grasa1 = "obesidad"
End Select
Case 40 To 59
Select Case Porcgra
Case 0 To 11: Grasa1 = "bajo en grasa"
Case 12 To 22: Grasa1 = "normal en grasa"
Case 23 To 28: Grasa1 = "alto en grasa"
Case Is > 28: Grasa1 = "obesidad"
End Select
Case 60 To 99
Select Case Porcgra
Case 0 To 13: Grasa1 = "bajo en grasa"
Case 14 To 25: Grasa1 = "normal en grasa"
Case 26 To 30: Grasa1 = "alto en grasa"
Case Is > 30: Grasa1 = "obesidad"
End Select
End Select
End Select
End Function


Ya podremos utilizar nuestra función Grasa1 en nuestra Hoja de cálculo, sobre tres celdas
=GRASA1(sexo; edad; %grasa)

14 comentarios:

  1. buenos dias estimados

    poseo un codigo condicional similar al del ejemplo sin embargo al seleccionar varias celdas o al agregar datos a varias celdas a la vez arooja un error me podrian indicar por que sucede esto?

    ResponderEliminar
    Respuestas
    1. Hola,
      tendría que ver el código.
      En principio esto es una función que requiere tres argumentos, que luego evalúa según cantidades.
      Habría que conocer cuantos argumentos tiene tu función, y si están correctamente definidas las condiciones.
      Supongo que si te devuelve un error será por que das más argumentos de los que tiene definidos, o bien, por que los valores no corresponden a las condiciones.
      Slds

      Eliminar
  2. buenos dias, estimados

    este es el codigo que poseeo el cual me da error
    espero me ayuden en este caso

    Dim Hora1 As String
    Dim Hora2 As String
    Dim Hora3 As String
    Dim Hora4 As String
    Dim Hora5 As String
    Dim Hora6 As String
    Dim Hora7 As String
    Dim Hora8 As String
    Dim Hora9 As String
    Dim Hora10 As String
    Dim Hora11 As String
    Dim Hora12 As String
    Dim Hora13 As String
    Dim Hora14 As String
    Dim Hora15 As String
    Dim Hora16 As String
    Dim Hora17 As String
    Dim Hora18 As String
    Dim Hora19 As String
    Private Sub Worksheet_SelectionChange(ByVal Target As Excel.Range)
    Hora1 = "00:00-07:00"
    Hora2 = "19:00-01:00"
    Hora3 = "19:00-00:00"
    Hora4 = "18:00-00:00"
    Hora5 = "13:00-19:00"
    Hora6 = "07:00-14:00"
    Hora7 = "09:00-16:00"
    Hora8 = "16:00-22:00"
    Hora9 = "07:00-13:00"
    Hora10 = "06:00-12:00"
    Hora11 = "08:00-14:00"
    Hora12 = "14:00-20:00"
    Hora13 = "08:00-15:00"
    Hora14 = "13:00-20:00"
    Hora15 = "08:30-14:30"
    Hora16 = "09:00-15:00"
    Hora17 = "15:00-22:00"
    Hora18 = "14:00-21:00"
    Hora19 = "08:00-13:30"
    Set Relcell = Range("Horario")
    If Not Application.Intersect(Relcell, Range(Target.Address(False, False))) Is Nothing Then
    Application.EnableEvents = False
    Select Case Target.Value
    Case Hora1
    Target.Value = "12:00 AM-07:00 AM"
    Case Hora2
    Target.Value = "07:00 PM-01:00 AM"
    Case Hora3
    Target.Value = "07:00 PM-12:00 AM"
    Case Hora4
    Target.Value = "06:00 PM-12:00 AM"
    Case Hora5
    Target.Value = "01:00 PM-07:00 PM"
    Case Hora6
    Target.Value = "07:00 AM-02:00 PM"
    Case Hora7
    Target.Value = "09:00 AM-04:00 PM"
    Case Hora8
    Target.Value = "04:00 PM-10:00 PM"
    Case Hora9
    Target.Value = "07:00 AM-01:00 PM"
    Case Hora10
    Target.Value = "06:00 AM-12:00 PM"
    Case Hora11
    Target.Value = "08:00 AM-02:00 PM"
    Case Hora12
    Target.Value = "02:00 PM-08:00 PM"
    Case Hora13
    Target.Value = "08:00 AM-03:00 PM"
    Case Hora14
    Target.Value = "01:00 PM-08:00 PM"
    Case Hora15
    Target.Value = "08:30 AM-02:30 PM"
    Case Hora16
    Target.Value = "09:00 AM-03:00 PM"
    Case Hora17
    Target.Value = "03:00 PM-10:00 PM"
    Case Hora18
    Target.Value = "02:00 PM-09:00 PM"
    Case Hora19
    Target.Value = "03:00 PM-09:00 PM"
    Case Else
    End Select
    Application.EnableEvents = True
    End If
    End Sub

    ResponderEliminar
  3. el error lo arroja sobre el case Hora1 al momento de pegar valores en el rango definido como "Horario" tambien ocurre error al arrastrar una celda del mismo rango

    ResponderEliminar
    Respuestas
    1. Hola,
      he probado tu macro (en Excel 2010, no se que versión empleas) y a mi no me devuelve ningún error.
      Lo que hace la macro sobre un rango de celdas, llamada 'Horario', evalúa el contenido, y si tiene exactamente la forma de la Hora1, Hora2, etc aplica el formato a esa misma celda con PM que tienes indicado en el SELECT CASE.
      He probado especificamente el caso Hora1 y no falla...
      si quieres envíame un correo a
      excelforo@gmail.com
      y te reenvío mi prueba.
      Slds

      Eliminar
  4. Buenas tardes amigo, como podria hacer un select case con rango de Meses(si los meses estan en B9:B12), por ejemplo:
    Select Case MESES
    Case "Enero"
    fobEn = Sheets("BASE DE DATOS").WorksheetFunction.SumIf(UCase("d2:d50596"), "1", "j2:j50596")
    Case "Febrero"
    fobFe = Sheets("BASE DE DATOS").WorksheetFunction.SumIf("d2:d50596", "2", "j2:j50596")
    Case "Marzo"
    fobM = Sheets("BASE DE DATOS").WorksheetFunction.SumIf("d2:d50596", "3", "j2:j50596")
    Case "Abril"... hasta diciembre..
    Agradeceria tu respuesta..

    ResponderEliminar
    Respuestas
    1. Hola José,
      depende de cuáles sean las variables de tu función (si es que hablamos de una función); MESES tendría que ser una variable, y deberías escribir mejor
      Case is ="Enero"
      fob=

      si escribes fobEn, fobFe, fobM, etc es como si te refiriereas a diferentes funciones. POr otro lado, parece que quieres aplicar la función SUMAR.SI según el mes anterior. Sería más cómodo hubieras definido una varable o dos para los rangos a evaluar y a sumar. Algo así:
      rngeval = Worksheets("BASE DE DATOS").Range("d2:d50596")
      rngeval = Worksheets("BASE DE DATOS").Range("j2:j50596")
      Select Case MESES
      Case is ="Enero"
      fob = Application.WorksheetFunction.sumif(rangeval,1,rngsuma)
      etc
      Intenta esas modificaciones, y si no das con ello, envíame el ejercicio a
      excelforo@gmail.com
      Slds

      Eliminar
    2. Hola, que tal? Una consulta, por ejemplo mi rango es de B9:M9 y a ese rango le he puesto nombre MESES Y he utilizado
      Select Case "MESES"
      Case "ENERO"
      .....
      Case "FEBRERO"
      .....
      esta bien asi o cómo podria hacer para que el caso ENERO se busque en el rango MESES, y asi para FEBRERO, y los demas meses
      Slds

      Eliminar
    3. Hola José Manuel,
      te contesto por mail.
      Según el fichero que me adjuntaste por mail, no es necesario usar SELECT CASE, simplemente definiendo las 12 funciones para cada mes, y luego incluirlo en el bucle DO LOOP.
      Slds

      Eliminar
    4. Muchas gracias. Me has ayudado un monton.. ahora si salen las respuestas para cada exportador..
      Gracias Excelforo
      Gracias Ismael.

      Eliminar
  5. Muy buenos días...!
    Estoy tratando de hacer una validación de ingreso al sistema a través de formulario y quiero que si es el ADMINISTRADOR tenga todas las opciones, que si es un VENDEDOR tenga otras opciones y así por el estilo, pero cuando hago referencia a un rango de celdas donde tengo los USUARIOS, CLAVES y TIPOS DE USUARIO me genera un error, quisiera saber que estoy haciendo mal.

    Como hago referencia a un rango de celdas a través de código VBA
    Muchas gracias..!


    Este es el código que tengo

    Private Sub CommandButton1_Click()
    Dim Usuario As String
    Dim Pass As String
    Dim Tipo As String
    Usuario = Worksheets("Hoja2").Range("a2:a10").Value ' Aquí me genera error inicialmente
    Pass = Worksheets("Hoja2").Range("b2:b10").Value
    Tipo = Worksheets("Hoja2").Range("c2:c10").Value
    If UserForm1.TextBox1.Text = Usuario And UserForm1.TextBox2.Text = Pass And UserForm1.TextBox3.Text = Tipo Then
    Select Case Tipo
    Case Administrador
    MsgBox " Soy el Administrador del sistema"
    Case Vendedor
    MsgBox " Soy el Vendedor del sistema"
    End Select
    Else
    MsgBox "No puede ingresar"
    End If

    ResponderEliminar
    Respuestas
    1. Hola Erwin,
      te contestaré a través del email que me me has enviado.
      Slds

      Eliminar
  6. Hola, se puede hacer una consulta???

    ResponderEliminar
    Respuestas
    1. Hola,
      puedes plantear tu pregunta por este medio.
      Un saludo

      Eliminar