martes, 4 de mayo de 2021

Contar días laborables indicados entre fechas

Hace unos días, en una formación, una alumna me preguntaba por la existencia de alguna función que calculara los días laborables transcurridos entre dos fechas, pero contando solo los días de la semana que ella indicara de manera personalizada.

Ella necesitaba personalizar los días laborables en cada caso (solo Lunes y Jueves, o solo Lunes, Martes y Viernes, etc). Le desarrollé de manera improvisada una fórmula para salir del paso; pero tras acabar la formación, pensé en hacer esa fórmula más general y extensiva para cualquier caso.
Y ese es el tema de hoy.
Contar días laborables indicados entre fechas

Dada una fecha inicial (celda B2) y otra final (celda C2), queremos conocer cuántos días de los elegidos en la celda D2, abreviados con una letra (L,M,X,J,V,S,D) y separados por la barra vertical, indiquemos (ejemplo: L|J, o L|X|S|D, etc).

Emplearé la función LET (a la espera la función LAMDA sea de uso general).
Así mismo emplearé en el desarrollo dos cálculos ya vistos en el blog:
- Separar caracteres (ver aquí)
- Producto de condiciones con criterio lógico O (ver aquí)

Con los antecedentes expuesto, veammos la fórmula buscada en E2:
=LET(FechaInicial;B2;
FechaFinal;C2;
DiasLab;TRANSPONER(XMLFILTRO("<i><f><d>"&SUSTITUIR(D2;"|";"</d><d>")&"</d></f></i>";"//f/d"));
SerieEntreFechas;SECUENCIA(FechaFinal-FechaInicial+1;1;FechaInicial);
DiasSemana;DIASEM(SerieEntreFechas;2);
PosDiasLab;COINCIDIR(DiasLab;{"L"\"M"\"X"\"J"\"V"\"S"\"D"};0);
Coincidencias;DiasSemana=PosDiasLab;
SUMAPRODUCTO(MMULT(--Coincidencias;SECUENCIA(COLUMNAS(Coincidencias);1;1;0)))
)
Contar días laborables indicados entre fechas


Podemos ver el paso a paso que realiza la fórmula descomponiendo cada línea...
El primer paso es simple y ya visto:
DiasLab;TRANSPONER(XMLFILTRO("<i><f><d>"&SUSTITUIR(D2;"|";"</d><d>")&"</d></f></i>";"//f/d"));
con esta función dividimos un cadena de texto, como la del ejemplo: L|V, en un vector de n columnas {L\V}.

En el siguiente paso generamos la serie de todas las fechas posibles entre las dos dadas con la función SECUENCIA:
SerieEntreFechas;SECUENCIA(FechaFinal-FechaInicial+1;1;FechaInicial)
obteniendo un vector de dichas fechas...
A continuación calculamos para cada fecha de nuestra serie aplicándole la función DIASEM:
DiasSemana;DIASEM(SerieEntreFechas;2)
esto nos convierte la serie de fechas en un nuevo vector de números del 1 al 7 (con una equivalencia: lunes=1, martes=2,..., domingo=7).
Un paso importante es el siguiente. Aquí obtenemos y transformamos el texto de días buscados en números del 1 al 7. Esto es, si busco L|V, necesito un 1 y un 5.
Esto lo conseguimos con la función COINCIDIR: PosDiasLab;COINCIDIR(DiasLab;{"L"\"M"\"X"\"J"\"V"\"S"\"D"};0)
Ya casi estamos...
Si cruzamos ambos vectores: días buscados con días listados:
Coincidencias;DiasSemana=PosDiasLab
obtendremos una matriz de FALSOS y VERDADEROS de acuerdo a dichas coincidencias...
Solo nos queda sumar y acumular coincidencias. Último paso:
SUMAPRODUCTO(MMULT(--Coincidencias;SECUENCIA(COLUMNAS(Coincidencias);1;1;0)))
Con la técnica descrita aquí, tendremos nuestro resultado final...
Contar días laborables indicados entre fechas

Listo. Tenemos una fórmula personalizada para obtener el número de días laborables, personalizados por nosotros, entre dos fechas dadas.

Finalmente, podríamos incorporar el concepto de festivos:
En la celda E3 y teniendo el cuenta el rango de festivos dado en B7:B9.
=LET(FechaInicial;B2;
FechaFinal;C2;
rangoFestivos;B7:B9;
DiasLab;TRANSPONER(XMLFILTRO("<i><f><d>"&SUSTITUIR(D2;"|";"</d><d>")&"</d></f></i>";"//f/d"));
SerieEntreFechas;SECUENCIA(FechaFinal-FechaInicial+1;1;FechaInicial);
DiasSemana;DIASEM(SerieEntreFechas;2);
PosDiasLab;COINCIDIR(DiasLab;{"L"\"M"\"X"\"J"\"V"\"S"\"D"};0);
Coincidencias;DiasSemana=PosDiasLab;
CruceFestivos;-MMULT(SI(SerieEntreFechas=TRANSPONER(rangoFestivos);1;0);SECUENCIA(FILAS(rangoFestivos);1;1;0));
SUMA(--((MMULT(--Coincidencias;SECUENCIA(COLUMNAS(Coincidencias);1;1;0))+CruceFestivos)>0)))

Contar días laborables indicados entre fechas
¡¡Anticipo!!. En dos días publicaré una solución estándar de Excel.

No hay comentarios:

Publicar un comentario

Nota: solo los miembros de este blog pueden publicar comentarios.