lunes, febrero 27, 2012

Análisis de encuestas con Formato Condicional

Las mejoras e innovaciones introducidas  han convertido a Formato Condicional en el nuevo Excel (2007/2010) en una aun más excelente herramienta para analizar datos. En esta nota mostraré como usar Formato Condicional para resumir en forma eficiente y sencilla los resultados de una encuesta.

Hace unas semanas recibí una consulta sobre como resumir concisamente una encuesta sobre el nivel de servicio de ciertos departamentos de una empresa. La encuesta fue montada usando la herramienta Formularios de la aplicación Documentos de Google.

Google va acumulando los resultados en una hoja de cálculo que puede descargarse a Excel. Los encuestados debían calificar en una escala de 0 (pésimo) a 5 (excelente) el funcionamiento de ciertos departamentos de servicios de la empresa.



Veremos como podemos crear una “termo-mapa” para mostrar en forma concisa y práctica los resultados de la encuesta.

Empezamos por convertir la matriz de los resultados en una tabla (Insertar-Tabla)



El próximo paso es crear una tabla dinámica, que ubicamos en una nueva hoja. Personalmente no me agrada el diseño por defecto de las tablas dinámicas en el nuevo Excel, por lo que uso Opciones de tablas-Mostrar para definir el diseño clásico de tabla dinámica que también permite arrastrar los campos a la cuadrícula



Arrastramos le campo de departamentos al área de las filas y cada uno de los campos de las preguntas al área de los valores. Resumimos los valores con la función Promedio y ajustamos el formato de los números.



Quitamos “Promedio de” en los encabezados de la columna para hacerlos más legibles.

Seleccionamos el área de valores y aplicamos Formato Condicional –Escala de Color



El resultado habla por si mismo.



Cuanto más verde es el fondo, mejor la calificación y, por lo contrario, cuando más rojo peor la calificación. Claramente podemos ver que el mejor departamento en la calificación general es Recursos Humanos. El nivel de servicio del Taller es claramente deplorable!

martes, febrero 21, 2012

Validación de datos en varias hojas – código mejorado

Gracias al comentario del amigo Juan Munevar en mi nota anterior, vimos que el código para evitar duplicados a través de varias hojas tiene un inconveniente: si la propiedad "mover después de presionar Entrar" está activada el código puede borrar el contenido de la celda equivocada.



Para que el código de la anterior funcione, la propiedad "mover después de presionar Entrar" debe estar desactivada



Como no podemos saber de antemano cuál es la definición del cuaderno debemos escribir un código para cubra todas las posibilidades. Lo que debemos tomar en cuenta es el orden de los eventos cuando apretamos Entrar.
El código evalúa el valor de la celda que era la celda activa al disparar el evento (Target). Es decir, si la opción de mover la selección después de apretar Entrar no está activada, borramos el contenido de la celda activa que es la misma que Target; si se mueve a la izquierda Target se encuentra a la derecha de la celda activa; si se mueve hacia abajo, Target se encuentra arriba; si se mueve hacia arriba, Target es la celda inmediata inferior.
Un caso particular es si la selección se mueve a la izquierda. En este caso, si la celda evaluada está en la columna A, Target coincide con la celda activa ya que Excel no puede seleccionar una celda que no existe.

En definitiva, el código es el siguiente:

Sub valid_accross_sheets(valValue)
   
    Dim iValCalc As Integer
   
    iValCalc = WorksheetFunction.CountIf(Range("Lista1"), valValue) + _
                WorksheetFunction.CountIf(Range("Lista2"), valValue) + _
                 WorksheetFunction.CountIf(Range("Lista3"), valValue)
   
   
    If iValCalc > 1 Then
        MsgBox "El valor " & ActiveCell.Value & " ya existe"
        Select Case Application.MoveAfterReturn
            Case Is = False
                ActiveCell.ClearContents
            Case Else
                Select Case Application.MoveAfterReturnDirection
                    Case Is = xlDown
                        ActiveCell.Offset(-1, 0).ClearContents
                    Case Is = xlUp
                         ActiveCell.Offset(1, 0).ClearContents
                    Case Is = xlToRight
                        ActiveCell.Offset(0, -1).ClearContents
                    Case Is = xlToLeft
                        If ActiveCell.Column = 1 Then
                            ActiveCell.ClearContents
                        Else
                            ActiveCell.Offset(0, 1).ClearContents
                        End If
                    End Select
        End Select
                   
    End If
 
End Sub


El cuaderno puede descargarse aquí.

sábado, febrero 18, 2012

Validación de datos en múltiples hojas de un cuaderno Excel

Allá por el 2007 publiqué dos notas sobre cómo aplicar validación de datos entre valores que se encuentran en varias hojas de un mismo cuaderno. La idea era impedir la entrada de valores duplicados en el cuaderno, sin importar en que hoja.

Después de una búsqueda en la Internet, encontré un pequeño comentario de Bob Umlas (Excel MVP):

Data validation across sheets isn't supported. You may need an event macro with code to do the checking for you as the worksheet changes (no se puede aplicar validación de datos a través de varias hojas. Habría que usar una macro de tipo evento para hacer la comprobación a medida que se van introduciendo cambios en la hoja).

En las notas mostré dos métodos con fórmulas en contradicción con el comentario de Umlas. El problema con los métodos que expuse en mis notas es que no funcionan. Así que como gesto de contrición y arrepentimiento (que viene a ser lo mismo), aquí va mi nota sobre como validar datos a través de las hojas de un cuaderno utilizando Vba (macros).

Siguiendo con el ejemplo que expuse en esas notas, tenemos un cuaderno con tres hojas; en cada hoja hay una lista de nombres. La idea es que no podamos ingresar en cualquiera de las listas un nombre que ya existe en cualquiera de las otras listas.



Para cada lista hemos creado un nombre que se refiere al rango en forma dinámica (con la función DESREF)



=DESREF(Hoja1!$A$2;0;0;CONTARA(Hoja1!$A:$A)-1;1)

=DESREF(Hoja2!$A$2;0;0;CONTARA(Hoja2!$A:$A)-1;1)

=DESREF(Hoja3!$A$2;0;0;CONTARA(Hoja3!$A:$A)-1;1)

Lo que hacemos ahora es crear un evento de manera que cuando se produzca un cambio en alguna de las hojas, el evento dispare una macro que controle si el nuevo valor introducido en alguna de las tres listas ya existe.

El código de la macro que hace esta tarea es:

Sub valid_accross_sheets(valValue)
   
    Dim iValCalc As Integer
   
    iValCalc = WorksheetFunction.CountIf(Range("Lista1"), valValue) + _
                WorksheetFunction.CountIf(Range("Lista2"), valValue) + _
                 WorksheetFunction.CountIf(Range("Lista3"), valValue)
   
    If iValCalc > 1 Then
        ActiveCell.ClearContents
        MsgBox "El valor " & ActiveCell.Value & " ya existe"
    End If
 
End Sub


Esta macro usa la función CONTAR.SI de Excel para comprobar cuantas veces aparece el valor de la celda activa (en la que hemos introducido el valor). Si el valor aparece más de una vez, el contenido de la celda activa es borrado y aparece un mensaje diciendo que el valor ya existe.

El valor de la celda activa es pasado a la macro por evento Workbook_SheetChange del objeto ThisWorkbook. Usamos este evento para evitar tener que programar un evento para cada hoja



El código es muy sencillo: hace una llamada a la macro valid_accross_sheets(valValue) pasando el valor de Target (la celda en la que hemos ingresado el nuevo valor).

Un detalle a tener en cuenta es que los rangos de los nombres deben ser continuos. Si dejamos una fila en blanco, el rango dinámico no incluirá el nuevo valor y la validación fallará.

El cuaderno con el ejemplo puede descargarse aquí.