miércoles, julio 01, 2009

Cálculos frecuencias en Excel usando tablas dinámicas

Un lector me consulta cómo crear un reporte que muestre cuántos de los artículos de un inventario tienen una antigüedad de hasta 3 meses, cuántos entre 3 y 6 meses, cuántos entre 6 y 9 y así sucesivamente.

Hay varias formas de hacer esto, pero cuando tenemos que enfrentarnos con listas de muchos artículos, digamos centenas o miles, la herramienta más eficiente son las tablas dinámicas.

De hecho vamos a mostrar cómo crear una tabla de frecuencias usando tablas dinámicas. EN nuestro caso lo aplicaremos al ejemplo del inventario.

Nuestro inventario se ve así



cálculo de frecuencia en Excel

EL primer paso es agregar un campo (columna) donde calculamos la antigüedad de cada artículo en relación a la fecha corriente. Usamos la función SIFECHA de esta manera


=SIFECHA(C2,HOY(),"m")

cálculo de frecuencia en Excel

Luego construimos una tabla dinámica, preferentemente en una hoja separada.


Ahora arrastramos el campo Antigüedad al área de campos de fila (si, a pesar de que Antigüedad es un campo de datos numéricos)

cálculo de frecuencia en Excel

Luego arrastramos los campos Artículo y Descripción al área de filas.

El campo Artículo lo volvemos a arrastrar pero esta vez al área de datos. Inmediatamente después quitamos los subtotales de todos los campos.

Nuestra tabla dinámica debe verse así

cálculo de frecuencia en Excel

Seleccionamos la celda A4 (Antigüedad) y apretamos el icono Ocultar detalle del asistente de Tablas Dinámicas

cálculo de frecuencia en Excel

El resultado es

cálculo de frecuencia en Excel

Ahora usamos Agrupar para crear los intervalos. En el formulario de agrupar ponemos 3 (o el tamaño de intervalo deseado) en la casilla Por

cálculo de frecuencia en Excel

Volvemos a elegir la celda A4 (Antigüedad) y nuevamente apretamos Ocultar Detalle.

El resultado es una tabla dinámica agrupada por intervalos de 3 meses, que totaliza el total de artículos en cada intervalo (0-2 meses, 3-5 meses, etc).

cálculo de frecuencia en Excel

Algunas observaciones:


# - Si queremos que el primer intervalo sea 1-3, deberemos modificar levemente la fórmula que calcula la antigüedad


=SIFECHA(C2,HOY(),"m")+1


Una vez modificada la fórmula, actualizamos la tabla dinámica

cálculo de frecuencia en Excel

# - La función HOY() que usamos en la fórmula de antigüedad es volátil, lo cual puede influir negatívamente en el tiempo de recálculo en hojas con muchos datos. En lugar de HOY() podemos poner la fecha en relación a la cual queremos calcular la antigüedad en una celda fuera del rango de la lista o en un nombre.



Technorati Tags:

lunes, junio 29, 2009

La función DIA.LAB (WORKDAYS) mejorada

En la nota anterior mencionamos que la función DIA.LAB (WORKDAY) de Excel adolece del mismo problema como su hermana mayor DIAS.LAB (NETWORKDAYS). Si bien ambas aceptan un rango de fechas como feriados, los días sábado y domingo son considerados fin de semana y por lo tanto no laborales.
No hay forma de cambiar esta definición y si nos ha tocado vivir en alguna parte del mundo donde el fin de semana no es el sábado y el domingo (como en gran parte de los países musulmanes e Israel), estas funciones dan resultados inexactos
.
Ayer mostramos dos soluciones a este problema en lo que respecta a DIAS.LAB. Las fórmulas matriciales propuestas por Chip Pearson y la una UDF (función definida por el usuario) del autor de estas líneas.

Hoy veremos cómo resolver el problema opuesto al planteado ayer: dada la fecha inicial y la cantidad de días hábiles necesarios para completar una misión, cuál será la fecha final.

Si vivimos en cualquier país de Occidente y los días de labor corren de lunes a viernes, podemos usar la función DIA.LAB nativa de Excel. Por ejemplo, si queremos saber cuál será la fecha después de cinco días hábiles empezando el 06/04/2009, DIA.LAB nos da estas respuestas



Excel días laborales

La celda C4 da la respuesta sin tomar en cuenta los feriados; la celda C5 es la fecha calculada tomando en cuenta los feriados (en España).

Pero ¿qué pasa si en nuestro proyecto no se trabaja los martes y jueves en lugar de los sábados y domingos?

Para solucionar este problema usaremos una función definida por el usurario (UDF), FechaFinal

Function FechaFinal(fecha_inicial As Date, _
dias_habiles As Long, _
diasIncluidos As Range, _
Optional feriados As Range)

'JLD Excel blog en Castellano
'Desarrollada por Jorge Dunkelman
'Junio 2009

Dim daysCounter As Long, tmpDays As Date, dateCheck

tmpDays = fecha_inicial + 1
daysCounter = 1

On Error GoTo ErrorHandler


If feriados Is Nothing Then
Do
tmpDays = tmpDays + 1
dateCheck = " "
dateCheck = WorksheetFunction.Match(Weekday(tmpDays, vbMonday), diasIncluidos, 0)
If IsNumeric(dateCheck) Then
daysCounter = daysCounter + 1
End If

Loop Until daysCounter = dias_habiles

Else

Do
tmpDays = tmpDays + 1
dateCheck = " "
dateCheck = WorksheetFunction.Match(CLng(tmpDays), feriados, 0)
If Not IsNumeric(dateCheck) Then
dateCheck = " "
dateCheck = WorksheetFunction.Match(Weekday(tmpDays, vbMonday), diasIncluidos, 0)
If IsNumeric(dateCheck) Then
daysCounter = daysCounter + 1
End If
End If
Loop Until daysCounter = dias_habiles
End If

FechaFinal = tmpDays

Exit Function

ErrorHandler:
dateCheck = "A"
Resume Next


End Function


Los argumentos de la función FechaFinal son
Excel días laborales

Fecha_Inicial: la fecha de incio del proyecto escrita con formato de fecha o una referencia a una celda que contiene esta fecha

Dias_Habiles: un número entero que indica la cantidad de días hábiles a contar desde elprimer día del proyecto

Dias_Incluidos: los días de la semana a tomar en cuenta (1 = lunes, 2 = martes, etc.)

Feriados (opcional): un rango que contiene las fechas de los feriados relevantes.

Los resultados de nuestro ejemplo son:
Excel días laborales




Technorati Tags:

La función DIAS.LAB versión mejorada

Excel viene provista con la función DIAS.LAB (NETWORKDAYS) que permite calcular la cantidad de días hábiles transcurridos entre dos fechas. En Excel 2007 esta función figura en la lista que muestra el asistente de funciones. En las versiones previas, hay que tener instalado el complemento Analysis Toolpak para que la función esté disponible.


funcion DIAS.LAB mejorada


Esta función permite tomar en cuenta las fechas de los feriados como argumento opcional, lo que la hace muy útil e “internacional”.

Pero también tiene una seria desventaja: en algunos países la semana de trabajo no comienza el lunes y no necesariamente los días de descanso son el sábado y el domingo. Por ejemplo en Egipto, Jordania Irak y Siria la semana laboral va de domingo a jueves y el fin de semana incluye el viernes y el sábado. En Israel la semana laboral corre de domingo a jueves o al mediodía del viernes. La función no permite cambiar estas definiciones lo que hace que en algunos países los resultados sean inexactos.

Lo mismo sucede si queremos calcular cuántos días tomará realizar un determinado proyecto cuando ciertos días de la semana no se realizan tareas relacionados con éste.

Empecemos por plantear el problema. Queremos saber cuántos días hábiles hay en el mes de abril del año 2009.


funcion DIAS.LAB mejorada


El resultado, que no toma en cuenta los feriados de abril, es 22 días. Para los lectores escépticos he agregado un calendario dinámico que muestra el mes de la fecha que aparece en la celda D2 (construido con la técnica que muestro en esta nota).

Tomemos como ejemplo España y agreguemos a nuestra fórmula los feriados del año 2009 (que aparecen en el rango G3:G14 de la hoja)


funcion DIAS.LAB mejorada
Vemos que el número de días hábiles es ahora 20 (el 12 de abril cae un domingo).

Nuestro problema empieza si vivimos en Jordania o Israel, o si en nuestro proyecto no se trabaja los martes y jueves, por ejemplo.

Chip Pearson propone dos soluciones a este problema usando fórmulas matriciales. Una fórmula que no toma en cuenta los feriados y una segunda que sí los incluye.

Tomemos el ejemplo anterior y supongamos que los días no laborales en nuestro proyecto son el martes y el jueves (días 2 y 4 de la semana respectivamente). La siguiente fórmula matricial permite calcular los días laborales, donde el sábado y el domingo lo son

=SUMA(SI(ESERROR(COINCIDIR(DIASEM(FILA(INDIRECTO(inicio&":"&fin)),2),dias_excluidos,0)),1,0))


funcion DIAS.LAB mejorada

Para que la fórmula sea más legible usamos los nombres

inicio = $C$2

fin = $C$3

días_excluidos = =DESREF(matricial!$F$4,0,0,CONTARA(matricial!$F$4:$F$35),1)

Para tomar en cuenta también los feriados debemos complicar un poco (bastante) la fórmula. Siguiendo con nuestro ejemplo, creamos un rango llamado “feriados” (B8:B19 en nuestro ejemplo) y lo incluimos en un nombre usando la función DESREF para que sea dinámico:

feriados =DESREF('matricial feriados'!$B$8,0,0,CONTARA('matricial feriados'!$B$8:$B$372),1)

La fórmula matricial es

=SI(O(inicio<=0,fin<=0,inicio>fin,ESNUMERO(inicio)=FALSO,ESNUMERO(fin)=FALSO),NOD(),SUMA(SI(ESERROR(COINCIDIR(DIASEM(FILA(INDIRECTO(inicio&":"&fin))),dias_excluidos,0)),SI(ESERROR(COINCIDIR(FILA(INDIRECTO(inicio&":"&fin)),feriados,0)),1,0)),0))


funcion DIAS.LAB mejorada
Recordemos una vez más que las fórmulas matriciales deben ser introducidas apretando simultáneamente Ctrl+Mayúsculas+Enter.

En lugar de las fórmulas matriciales propuestas por Pearson podemos crear una UDF (user defined functions, funciones definidas por el usuario).

En esta UDF el argumento “feriados” es opcional.


Function DiasLabMejorada(fecha_inicial As Date, _
                            fecha_final As Date, _
                            diasExcluidos As Range, _
                            Optional feriados As Range)
                            
'JLD Excel blog en Castellano
'Desarrollada por Jorge Dunkelman
'Junio 2009

    Dim daysCounter As Long, tmpDays As Date, dateCheck
    
    tmpDays = fecha_inicial + 1
    daysCounter = 0
    
    On Error GoTo ErrorHandler
    
    If feriados Is Nothing Then
    Do While tmpDays < fecha_final
        dateCheck = " "
        dateCheck = WorksheetFunction.Match(Weekday(tmpDays, vbMonday), diasExcluidos, 0)
        If Not IsNumeric(dateCheck) Then
            daysCounter = daysCounter + 1
        End If
        tmpDays = tmpDays + 1
    Loop
    
    Else
    
    Do While tmpDays < fecha_final
    dateCheck = " "
    dateCheck = WorksheetFunction.Match(CLng(tmpDays), feriados, 0)
    If Not IsNumeric(dateCheck) Then
        dateCheck = " "
        dateCheck = WorksheetFunction.Match(Weekday(tmpDays, vbMonday), diasExcluidos, 0)
        If Not IsNumeric(dateCheck) Then
            daysCounter = daysCounter + 1
        End If
    End If
        tmpDays = tmpDays + 1
    Loop
    End If
    
    DiasLabMejorada = daysCounter
    
   Exit Function
  
ErrorHandler:
dateCheck = "A"
Resume Next

    
End Function



Para usar esta UDF debemos guardarlo en un módulo común del editor de VB. Si lo hacemos en el cuaderno Personal.xls, podemos usar la función en todo cuaderno abierto.


En la próxima nota veremos como calcular la fecha final dados la fecha inicial y la cantidad de días hábiles a tomar en cuenta. Como en el caso de DIAS.LAB, también la función DIA.LAB toma en cuenta los sábados y domingos como días no laborales, parámetros que no pueden ser cambiados.

Technorati Tags: