Calculate end date based on own particular work week

HI Everyone, I have an App in which I want select to configure a working week. A Enumlist where I choose the days in which I am going to execute my work:

Sunday

Monday

Tuesday

Wednesday

Thursday

Friday

Saturday

All are chosen by a check box.

Once the days have been chosen, I have to choose the start date of the work. Suppose I start today 3/17/2022 and that I will work Monday, Wednesday and Friday. Also assume a period of 30 business days. Also take into account holidays. What I need is to be able to calculate the end date of the work, taking into account a period of 30 business days, holidays and the previously chosen work week configuration.

This would give me a result with a date 10 weeks later if there is no holiday that falls on some of the days.

One of the formulas I used is WORKDAY() however it is limited as it only excludes Saturdays from the list, Sundays.

Is there a way to create my own WORKDAY formula excluding the days I want?

No matter how fancy the formula is, I’ll do it the same

@Steve @TeeSee1 @Joseph_Seddik

I cannot think of any single formula that does this. (I very quickly gave up,)

Here is a ‘brute force’ approach that works but you may not like it.

Some preps

  • create a Holidays table which simply lists holidays that you do not want to include as part of your work/business days.
  • in your main table, create a temporary [count down] with Initial Val to [Required Business Days] <= you can use [Required Business Days] but wanted to preserve it.

Then, Create a actions below

  1. Start of the sequence

  2. Move End Date by one day

  3. Reduce [count down] if it falls on the weekdays you chose AND not in the holidays table

  4. Go back to 1. if [count down] > 0

Looping process is something AppSheet cannot do in an elegant way. (No Code :grin: )

If you are interested I can share the demo app..

2 Likes

Perfecto @TeeSee1 apenas despierte la vemos !

Wow ! Were you tapping the calls some 10 days ago? :grinning_face_with_smiling_eyes:

I’ve implemented this very same requirement as part of a project presentation to a customer, and will be happy to share with the community. Let me just isolate it and do some UX translation to English and will post the sample app. No actions or complexities involved; just simple expressions.

3 Likes

Wow!!! Joseph!! espectacular, Yo al menos de mi parte te agradecería mucho poder ver como lo has resuelto. Por ahora te comento como voy haciendolo (a la manera de un cavernícola no programador como yo soy).

Tengo como dato:

  • Fecha de inicio del proyecto
  • Número de días que dura el trabajo
  • Cantidad de días trabajados por semana (que es una columna que se calcula sola en función de la selección del usuario de datos de una enumlist donde están los días de semana); si selecciono 5 días, la cantidad de días trabajados será 5
  • Fecha de finalización: que es un cálculo que hago de la siguiente manera

([Fecha de Inicio]-1)+(FLOOR([Plazo en días]/[Días laborales por semana])*7)+

(

([Plazo en días]/[Días laborales por semana])-

FLOOR([Plazo en días]/[Días laborales por semana])

)*([Días laborales por semana])

Esto me permite conocer cuanto se desplaza la fecha pero no es muy exacto y tampoco profesional. Estoy seguro que tu tienes algo muy profesional para mostrar. Te agradezco si puedes corregirme.

Ahora estoy por hacer un “recalculo” teniendo en cuenta los días festivos que hay en el lapso desde el inicio hasta la fecha final y luego recalcular la fecha final. Tengo que aclarar para que no te rias, soy un principiante, pero no me quedó más remedio que ingeniarmela para obtener el resultado. Si pudiera contar con algo como lo tuyo sería ideal.

COUNT(
SELECT(
Feriados[Fecha Feriado],
[Fecha Feriado]>=[Fecha de Inicio],
[Fecha Feriado]<=[Fecha Final 1]
)
)

luego recalculo y obtengo

([Fecha de Inicio]-1)+(FLOOR(([Plazo en días]+[Feriados])/[Días laborales por semana])7)+((([Plazo en días]+[Feriados])/[Días laborales por semana])-FLOOR(([Plazo en días]+[Feriados])/[Días laborales por semana]))([Días laborales por semana])

Lo que tengo que hacer ahora es desplazar la fecha un día más si coinide con un día no laboral, haciendo que termine en un día laborable. Esta solución es muy rústica.

Here it is, I’ve changed the display names to English, but was too lazy to change the expressions, but I think you’ll be able to relate. In any case, please tell me if you have any difficulties.

Todavía no he leído en detalle tu última respuesta, perdón amigo, voy a leerla más tarde con tranquilidad y te contesto.

Target Workday Calculator 2

3 Likes

Joseph te agradezco mucho tu buena forma de ser

1 Like

Tengo una duda respecto a cómo adaptarlo Joseph, Tu tienes en la App una vista de “Semana” donde puedes configurar la semana laborable sin embargo yo debo hacerlo para cada trabajo y dentro del formulario de trabajo. Para ello he adoptado una EnumList donde simplemente selecciono los días laborables de la semana y se crea una lista con los días que necesito. La diferencia radica en que en la fórmula de tu app haces referencia a una condición adoptada en la vista semana (Laborable o No laborable)

TOP(
SELECT(

Dates[Date],

AND(
[Date] > [_ThisRow].[Date de début],
[Ouvrable]
)

),[Nombre de jours]
)

Sin embargo lo que yo necesito es adaptar esta fórmula para que, cuando yo seleccione directamente un elemento de la enumlist, los elementos seleccionados se consideren laborables.

Es eso posible?

Respecto del “Target Day” a menos que sea considerado como fecha no incluida desde el inicio del conteo, estarías sumando un día más al plazo.

Lo normal sería que si se arranca a trabajar un 1/3/2022 (todo el día) y tienes 20 días de plazo, el día 20/3/2022 termine el trabajo al final de la jornada, ya que se incluye el primer día como día completo trabajado dentro de los 20 de plazo. Si no se incluye este día, entonces está bien. Al menos en mi app es así, incluyo el día inicial dentro de los días hasta la fecha final.

Hola Gus,

Una expresión similar fue la primera que he considerado mentalmente, pero el problema es que cuando desplaces la fecha target por el número de fechas no laborales y festivos encontrados, es muy probable que encuentres más días de este tipo y tendrás que desplazar de nuevo y será posible encontrar más días no laborales de nuevo, por eso descarté esta vía por la imposibilidad de ser controlado sobre todo porque el número de días del proyecto es indefinido.

Aparte de eso, bien hecho :slightly_smiling_face: la creatividad es el mejor amigo al desarrollador.

1 Like

El cálculo en realidad no se hace aquí, pero en la tabla Dates, columna “Ouvrable”.

AND(
NOT( IN( WEEKDAY([Date]), SELECT(Semaine[Index], FALSE = [Ouvrable]) )),
NOT( IN([Date], Jours Fériés[Date]) )
)

Esta es la formula que asigna el estado laboral o no laboral a una fecha.

Ahora sobre la necesidad de hacer el cálculo por un trabajo. Esto es lo normal, lo esperado. Pero la cuestión es ¿cómo abordarlo? Primero, sí es posible adaptar la app para incorporar esta función y asignar fechas por trabajo, pero ¿sería el camino correcto?

Muchos desarrolladores suelen olvidarse de que la arquitectura del software es mas importante de su codificación. Sí, con algunos trucos de magia de codificación, se podría crear expresiones complejos con las cuales se incorporarán el calculo de fechas por proyecto y por usuario, etc. pero para mí esto sería una falta grave. Era exactamente el tema principal de mi presentación :slightly_smiling_face: KISS - Keep It Smart & Simple

La app se trata de una calculadora que se puede incorporar en contextos más grandes. El caso del cliente era más complejo, pero también en tu caso no necesitas hacer algo más para hacer el cálculo por trabajo:

  • Quédate con la tabla “Calculatrice” en tu app.
  • Tu tabla de Trabajos, debe tener las columnas: “Fecha Inicio”, “Días laborales de la semana”, “Nombre de Días” y “Fecha Final”.
  • Puedes copiar la expresión de “Date Cible” en “Fecha Final”, o añadir una columna “TrabajoID” en “Calculatrice” y utilizar las Dereference Expressions para copiar el valor (en lugar de la expresión) de “Date Cible” en “Fecha Final”.
  • Cuando añades un trabajo nuevo en la tabla Trabajos, en ese momento puedes elegir los días correspondientes, o hacerlo antes.

Los datos de un trabajo en la tabla de Trabajos serán guardados en columnas normales en el spreadsheet, y así no serán cambiados si por ejemplo los días laborales han sido cambiados según un nuevo proyecto.

Además, puedes impedir que esos datos se cambien al editar la fila, poniendo la siguiente condición en el campo Editable? de cada columna:

ISBLANK([_This])

Así, una vez creado un trabajo, la información dinámica relacionada con los cálculos de fechas no se cambiarán nunca.

2 Likes

@Gustavo_Eduardo Yo calculaba basándome en que el día del inicio NO está incluido, pero el día final Sí.

Si quieres incluir ambos días, en la expresión tendrás que cambiar:

[Date] > [_ThisRow].[Date de début]

por:

[Date] >= [_ThisRow].[Date de début]

2 Likes

Just for anyone who might be interested..

https://www.appsheet.com/portfolio/3401559

“work days”

2 Likes

Perfecto Joseph, así lo hice como me lo planteas y está bien funciona.

@TeeSee1 wow recien veo esto. Es otra manera de llegar a los valores. En este momento me estoy manejando con la respuesta de Joseph pero con gusto la estudio! Te agradezco que me hayas permitido verla! Saludos

Joseph, no sería lo mismo, e incluso algo más simple si a la expresión de cálculo la planteas así:

AND(
IN( WEEKDAY([Date]), SELECT(Semaine[Index], TRUE= [Ouvrable]) ),
NOT( IN([Date], Jours Fériés[Date]) )
)

Sí, es lo mismo, solo es una cuestión de estilo para mejorar la legibilidad (en mi pdv).

Yo digo: selecciona las fechas que NI son laborales en la semana, NI son festivos.

Tú dices: selecciona las fechas que SÍ son no laborales, pero NO son festivos.

2 Likes

Como estás @TeeSee1 Buen día, voy a intentar probando con tu solución. La forma que me da Joseph es buena pero mi app se pone muy lenta. Una vez que realice ambas adaptaciones pruebo y les comento.

Una pregunta Joseph! supongamos que tenemos trabajos de más de un año de demora y que la lista de fechas es pequeña.

No hay una manera de generar una lista virtual entre dos fechas de forma que podamos poner una fecha límite y una fecha de inicio de la lista y no todas las fechas del 2022, 23, … 2070

Es obvio que quizás para esa época ya no exista Appsheet pero pienso que una lista carga mucho a la app. Por ahí una lista virtual sea menos pesada no crees?

Generar una lista dinámica implica utilizar Actions. Es posible, pero si lo prefieras, sería más sencillo utilizar la solución propuesta por @TeeSee1

Sin embargo, no creo que la lista de fechas cargaría la app o tendría un impacto sobre su rendimiento; porque la SELECT siempre se lanza en una tabla con solo siete filas.

De todas formas la expresión en Dates se puede mejorar impidiendo el cálculo para las fechas antiguas, por ejemplo así:

IF( [Date] < TODAY(),
FALSE,
AND( … )
)

2 Likes