Imprimir página | Cerrar ventana

Fechas y días de plazo

Impreso de: Foro de Access y VBA
Categoría: Access y VBA
Nombre del foro: Access y VBA
Descripción del foro: Foro de programacion en Access (Con código y sin código)
URL: http://www.mvp-access.com/foro/forum_posts.asp?TID=86698
Fecha de impresión: 27/Marzo/2026 a las 06:03


Tema: Fechas y días de plazo
Publicado por: maserrano
Asunto: Fechas y días de plazo
Fecha de publicación: 24/Mayo/2023 a las 10:28
Buenos días.

Necesito en una "consulta" calcular la fecha futura, que sería el resultado de una fecha dada y "n" días de plazo (hábiles)", siendo además el resultado también una fecha hábil.
Los días inhábiles serían sábados, domingos y días de fiestas, que son propios de cada lugar, en este caso España.
Igual en el foro hay temas parecidos pero no doy con un ejemplo similar en características.
Gracias por adelantado.



Respuestas:
Publicado por: maxpro
Fecha de publicación: 25/Mayo/2023 a las 05:10
Hola.

Y que has intentado? has probado algo que puedas poner aqui para poder evaluarlo??


Saludos


-------------
-------Maxpro-------

San Luis - Argentina


Publicado por: maserrano
Fecha de publicación: 25/Mayo/2023 a las 09:23
Buenas.
Lo primero siento haber respondido tan tarde.
He intentado trabajar sobre un ejemplo de Emilio sobre cálculo de días hábiles entre dos fechas, pero no doy con el resultado que quiero y por ello he planteado la duda en el foro.
En este caso se introducen ambas fechas y te calcula el nº de días hábiles. Además incluye la posibilidad de incluir sábados como hábil (o no) y los festivos (o no), para lo que debe haber una tabla de festivos.
Yo intento adaptarlo a introducir una fecha y un nº de días hábiles para que me dé la fecha (hábil) transcurridos esos días.

En el desarrollo, hay una función (DiasHabiles), que me cuesta un poco entender. Lo transcribo:

Public Function DiasHabiles(ByRef datInicio As Date, ByRef datFin As Date, Optional blnSabados As Boolean = True, Optional blnFestivos As Boolean = False) As Integer
Dim lngDiasTotales As Long, _
    lngDiasFinDeSemana As Long, _
    datSwap As Date, _
    lngFestivos As Long, _
    rst As DAO.Recordset, _
    strSQL As String

On Error GoTo DiasHabiles_TratamientoErrores

'  en caso de que sea necesario intercambio fechas de inicio y fin
If datFin < datInicio Then
   datSwap = datInicio
   datInicio = datFin
   datFin = datSwap
End If

' días totales
lngDiasTotales = DateDiff("d", datInicio, datFin) + 1

' días que caen en fin de semana
lngDiasFinDeSemana = DateDiff("ww", datInicio, datFin) * IIf(blnSabados, 2, 1) + IIf(Weekday(datInicio) = vbSunday, 1, 0) + IIf(blnSabados, IIf(Weekday(datFin) = vbSaturday, 1, 0), 0)

' si se han de contar los festivos abro un recordset contra la tabla tblFestividades
If blnFestivos Then
   ' me aseguro de que existe la tabla tblFestividades
   If DCount("Name", "MSysObjects", "Name = 'tblFestividades'") = 0 Then
      Err.Raise 513, "DiasHabiles", "La tabla tblFestividades no existe"
      GoTo DiasHabiles_Salir
   End If
   strSQL = "SELECT [Fecha] "
   strSQL = strSQL & " FROM tblFestividades "
   strSQL = strSQL & " WHERE " & BuildCriteria("Fecha", dbDate, ">=" & datInicio & " AND <=" & datFin)
   
   Set rst = DBEngine(0)(0).OpenRecordset(strSQL, dbOpenDynaset)
   
   If Not (rst.EOF And rst.BOF) Then
      Do
         ' según cual sea el día de la semana acumulo o no la festividad
         Select Case Weekday(rst!Fecha)
            Case vbSunday     ' domingo
            Case vbSaturday   ' sábado
               If Not blnSabados Then lngFestivos = lngFestivos + 1
            Case Else         ' resto de días
               lngFestivos = lngFestivos + 1
         End Select
         rst.MoveNext
      Loop Until rst.EOF
   End If
End If
' devuelvo el resultado
DiasHabiles = lngDiasTotales - lngDiasFinDeSemana - lngFestivos


DiasHabiles_Salir:
   On Error GoTo 0
   If Not rst Is Nothing Then
      rst.Close

Por otro lado, el formulario, tiene eventos después de actualizar las fechas, que son:

Private Sub txtInicio_AfterUpdate()
If IsDate(Me.txtInicio) And IsDate(Me.txtFin) Then
   Me.txtDiasHabiles = DiasHabiles(Me.txtInicio, Me.txtFin, Me.chkSabados, Me.chkFestivos)
End If
End Sub

Private Sub txtFin_AfterUpdate()
txtInicio_AfterUpdate
End Sub

..., donde se llama a la función DiasHabiles, que coge los valores de ambas fechas y los box con las validaciones de sábados y festivos.
El evento de actualización de fecha lo entiendo, aunque la función es un poco compleja para mi; lo que no sé es cómo modificar los parámetros para preguntar por la fecha final en vez de los días que generan ambas fechas.
Gracias de nuevo.


Publicado por: maserrano
Fecha de publicación: 25/Mayo/2023 a las 09:28
El porqué de la modificación es por un tema de Administración. Conozco el día de una notificación (fecha de inicio) y el plazo que se le da para responder a esa notificación (nº de días hábiles), con lo que calculo la fecha máxima de esperar una respuesta del administrado, un dato que a priori no conozco; sólo el máximo otorgado.
Salu2


Publicado por: Mihura
Fecha de publicación: 25/Mayo/2023 a las 10:31
La función está hecha para darte los días hábiles entre dos fechas, no para partiendo de un día y el número de hábiles deseados obtener una fecha final.

Tendrás que desarrollar tu propia rutina, yo me plantearía un bucle:

- compruebo que sea día lectivo (función día de la semana) incluyendo o no sábados según un parámetro
- si lo es compruebo tabla festivos
- si es lectivo no festivo aumento el nº de días hábiles calculados en 1
- si he llegado a la cuenta que necesito ya tengo mi fecha -> fin bucle
- si no he llegado aumento la fecha de comparación en un día y vuelvo al comienzo del bucle




-------------
Jesús Mansilla Castells.
Saludos desde Móstoles.

http://www.accessaplicaciones.com" rel="nofollow - Access Aplicaciones
http://www.tecsys.es" rel="nofollow - Tecsys.es


Publicado por: maserrano
Fecha de publicación: 26/Mayo/2023 a las 01:10
Buenas de nuevo.
Estoy de tiempo... lo siento pero es el "directo" con los niños.
Veamos. Lo que he podido conseguir es introducir una fecha en un campo y, en primera instancia, dar un valor fijo de plazo administrativo (p.e. 10 días), para que me calcule otra fecha en otro campo con ese plazo.
Declaro las variables y cojo el valor introducido verificando que sea una fecha. Esa variable la convierto a Date para poder obtener el día, mes y año. Hago el cálculo con los datos fijados y vuelvo a convertir la fecha a Date para mostrarlo en un nuevo campo. ...,algo así:

Private Sub txtFNotifica_AfterUpdate()
Dim vFNotifica As String, vFVencimiento As String
Dim vDia As String, vMes As String, vAno As String
vFNotifica = Nz(Me.txtFNotifica.Value, "")
If vFNotifica = "" Then Exit Sub
If Not IsDate(vFNotifica) Then Exit Sub
vFNotifica = CDate(vFNotifica)
vDia = Day(vFNotifica)
vMes = Month(vFNotifica)
vAno = Year(vFNotifica)
vFVencimiento = vDia + 10 & "/" & vMes & "/" & vAno
vFVencimiento = CDate(vFVencimiento)
Me.txtFVencimiento.Value = vFVencimiento
End Sub

Supongo que si en vez de 10 días fijos quiero que sea un número a introducir, debo declararlo, recoger su valor (de un campo en el formulario) y pasarlo a CDate para poderlo calcular en la fecha de vencimiento.

Ahora viene lo complicado. El tema de días hábiles y festivos, que voy a intentar plantearlo como dice el Sr. Mihura a través de bucles. Me pongo con ello antes de que me entre más sueño y publico cuando lo tenga.
Por supuesto, se admiten sugerencias y ayudas. Gracias otra vez.


Publicado por: Mihura
Fecha de publicación: 26/Mayo/2023 a las 09:14
Lo estás complicando muuuuucho Wink.

Necesitas una fecha inicial (vale el campo del formulario), una variable tipo date con el día que estamos comparando, el nº de días lectivos que quieres (campo del formulario) una variable tipo integer para llevar la cuenta de los días lectivos que llevas en el bucle ... y ya tá.

Para sumar un dia a una fecha tienes el comando DateAdd o más espartanamente basta con sumarle 1.


-------------
Jesús Mansilla Castells.
Saludos desde Móstoles.

http://www.accessaplicaciones.com" rel="nofollow - Access Aplicaciones
http://www.tecsys.es" rel="nofollow - Tecsys.es


Publicado por: maserrano
Fecha de publicación: 26/Mayo/2023 a las 10:51
Todavía a eso no he llegado. Mis conocimientos de VBA son muuy básicos.
De hecho, en lo anterior propuesto hay un fallo, pues no puedo sumar "10" sin más, ya que si hay un cambio de mes (pe, 27 de marzo más 10 días) me salta el código en la línea:

vFVencimiento = vDia + 10 & "/" & vMes & "/" & vAno

vFVencimiento = CDate(vFVencimiento)

Para evitarlo, creo que debo coger el valor del plazo en un campo del formulario (declarandolo antes como una variable string, decir que ese valor es de tipo CDate e incluirlo en la línea:

vFVencimiento = vDia  & "/" & vMes & "/" & vAno

..., pero por más vueltas que le doy no lo logro.
(Y después debo incluirle las validaciones de sábados y festivos)




Publicado por: Mihura
Fecha de publicación: 26/Mayo/2023 a las 12:43
Mírate el comando DateAdd.

-------------
Jesús Mansilla Castells.
Saludos desde Móstoles.

http://www.accessaplicaciones.com" rel="nofollow - Access Aplicaciones
http://www.tecsys.es" rel="nofollow - Tecsys.es


Publicado por: maserrano
Fecha de publicación: 26/Mayo/2023 a las 16:32
Ok.
La verdad es que así es mucho más sencillo.
El código se reduce a:

Private Sub txtNumber_AfterUpdate()
Dim FirstDate As Date
Dim IntervalType As String
Dim Number As Integer
Dim FinalDate As Date

FirstDate = Nz(Me.txtFirstDate.Value, "")
Number = Nz(Me.txtNumber.Value, "")
IntervalType = "w"

FinalDate = DateAdd(IntervalType, Number, FirstDate)
Me.txtFinalDate.Value = FinalDate
End Sub

Una fecha, un número de plazo y nos da la nueva fecha. Ocurre que, según lo que he leído si el:

IntervalType lo ponemos como "w" en vez de "d", (weekday - Day),
no nos cuenta los fines de semana; pero no lo hace y da el mismo resultado.

Ahora intentaré implementar el tema de los festivos y sábados-domingos 


Publicado por: maserrano
Fecha de publicación: 26/Mayo/2023 a las 20:53

Por más vueltas que le doy lo logro cambiar la forma de pedir los datos.

Ahora tengo el evento:

Private Sub txtInicio_AfterUpdate()

If IsDate(Me.txtInicio) And IsDate(Me.txtFin) Then

   Me.txtDiasHabiles = DiasHabiles(Me.txtInicio, Me.txtFin, Me.chkSabados, Me.chkFestivos)

End If

End Sub

 

Pido el plazo de días que hay entre dos fechas, por las que pasa la función DiasHabiles que tiene en cuenta sábados, domingos y festivos.

Intento cambiar a pedir la fecha final si conozco la fecha inicial y el plazo de días. Pero no me da resultados; y no sé cómo modificarlo.

…estoy atascado



Publicado por: 01loko
Fecha de publicación: 26/Mayo/2023 a las 21:51
veamos si soy capaz de explicarme:
Con un formulario con dos campos: fecha inicio (fecha_ini) y fecha final (fecha_fin), un marco de opciones( tres opciones 10, 20 y 30 dias (con valores 10, 20 y 30) y un boton.
Private Sub Comando13_Click()
fechainicio = Me.fecha_ini
suma = 0
fechafinal = fechainicio + Me.Marco4
'ahora usamos la funcion fechaslaborables del MAESTRO MIHURA

Dim FechaBucle As Date, DiasLaborables As Integer
     For FechaBucle = fechainicio To fechafinal
         If Weekday(FechaBucle) = vbSaturday Or Weekday(FechaBucle) = vbSunday Then
             suma = suma + 1
             Else
                 DiasLaborables = DiasLaborables + 1
         End If
     Next
  fechafinal = fechafinal + suma
comprueba:
'comprobamos que la fecha final no sea fin de semana
  If Weekday(fechafinal) = vbSaturday Or Weekday(fechafinal) = vbSunday Then
  fechafinal = fechafinal + 1
  GoTo comprueba
  End If
  ' aqui faltaria comprobar las fechas de cada lugar
    Me.Fecha_fin = fechafinal
End Sub


creo que es lo que buscas, si no he entendido mal



-------------
Recordar de que soy nuevo y estoy aprendiendo.


Publicado por: maserrano
Fecha de publicación: 26/Mayo/2023 a las 22:50
Gracias por la aportación. La estudiaré.
Pero a primera vista difiere. Lo que tengo es una fecha,  un plazo (que es un campo donde puedo poner el valor que quiera, 10, 15, 20... días) y un campo resultado de fecha en el que no incluyo días sábado, domingos y festivos, o sea "laborables", que es el resultado de la fecha inicial más el plazo otorgado de días laborables. 
Esa es la ideaque no consigo resolver .
Gracias


Publicado por: maserrano
Fecha de publicación: 27/Mayo/2023 a las 00:19
Por cierto, dónde puedo encontrar la función Fechaslaborables del Sr. Miura.
¿esta función incluye tema de festivos?
Salu2


Publicado por: maxpro
Fecha de publicación: 27/Mayo/2023 a las 07:51
Hola.

Aqui Quizas: http://www.accessaplicaciones.com/ejemplos.html" rel="nofollow - http://www.accessaplicaciones.com/ejemplos.html no se si estara lo q buscas pero hay cosas interesantes que pueden llevarte a lo que necesitas para tu aplicacion. es cuestion de buscar, aprender, elaborar! Suerte!!


Saludos


-------------
-------Maxpro-------

San Luis - Argentina


Publicado por: maserrano
Fecha de publicación: 27/Mayo/2023 a las 19:39

Buenas. Llevo un rato intentando solucionarlo, hoy que tengo más tiempo, pero no doy con ello, la verdad. He llegado a dos caminos veamos,

·       - Por un lado, tengo un evento que me devuelve una fecha (final) una vez introducida una fecha inicial y un plazo de tiempo. Hasta aquí bien, pero no tiene en cuenta que sean días hábiles (o sea, ni sábados, ni domingos ni festivos). No sé crear una función que lo haga y la que he visto está preparada para solicitar dos fechas y devolver el plazo entre ambas, y no sé cómo adaptarla.

 ·       - Por otro lado, hay un ejemplo que sí tiene en cuenta el tema de los días hábiles; incluso puedo discriminar entre si quiero que cuenten los sábados y también los festivos. El “problema” es que este ejemplo pide dos fechas y calcula el plazo entre ambas y su función está adaptada a ello. Y, por más vueltas que le doy no consigo adaptarlo a que me devuelva la fecha, conocida la fecha inicial y el plazo.

 Por lo que la solución que tengo es adaptar mi trabajo a este último ejemplo, pues la variación es pequeña, cambiando el concepto de qué y cómo lo queremos.

Así pues, por mi parte se puede cerrar este hilo y dar gracias a todo el grupo. Salu2



Publicado por: mounir
Fecha de publicación: 28/Mayo/2023 a las 00:32
Hola!

Mírate estos dos enlaces y podrás adaptarlos a tus necesidades.

https://www.fmsinc.com/microsoftaccess/modules/examples/AddWeekdays.asp

https://stackoverflow.com/questions/15271090/add-working-days-to-start-date-to-create-end-date-including-bank-holiday

-------------
Un Saludo.


Publicado por: xavi
Fecha de publicación: 29/Mayo/2023 a las 08:57
Hola,

Como veo que llevas varios días de intentos, al final me decidí a probar de hacer la función. He emulado la función DIAS.LAB.INTL de Excel con alguna ligera variación.

Aquí puedes encontrarla:  http://www.llodax.com/smf/index.php?topic=237.0" rel="nofollow - Cálculo de dia laborable flexivo

A ver si te sirve

Un saludo


-------------
Xavi, un minyó de Terrassa

http://www.llodax.com" rel="nofollow - Mi web


Publicado por: maserrano
Fecha de publicación: 29/Mayo/2023 a las 14:58

Gracias Xavi.

La verdad es que me cuesta muchas veces ver las cosas, los detalles.

Aun así, comprobemos si soy capaz de ponerlo en marcha.

Hecha la función (DiaLabIntl), ahora se trata de probarlo en un ejemplo, donde tenemos:

-Lo primero crear una tabla (tblDatFestivos) con un campo llamado FechaFestiva

-Un formulario con un campo de fecha inicial: txtFechaInicial y otro campo de días de plazo a esa fecha (txtDiasProceso).

A este último campo, le aplico un evento de tipo después de actualizar donde llamo a la función; algo así:

 

Private Sub txtDiasProceso_AfterUpdate()

Dim FechaFinal As Date

FechaFinal = DiaLabIntl()

If IsDate(Me.txtFechaInicial) And IsString(Me.txtDiasProceso) And IsDate(Me.txtFechaFinal) Then

Me.txtFechaFinal = FechaFinal(Me.txtFechaInicial, Me.txtDiasProceso)

End If

End Sub

 

 

…, y en el campo txtFechaFinal debe de aparecer la fecha final como resultado de aplicarle a la inicial los días de plazo sin contar sábados, domingos y festivos.

 

Pero no me sale. De momento me dice en DiaLabIntl(), que el argumento no es opcional. He intentado con la ayuda F1 pero no me aclaro…




Publicado por: xavi
Fecha de publicación: 29/Mayo/2023 a las 17:47
Hola,

Estas haciendo mal la secuencia de acciones. Estas asignando a una variable FechaFinal la función sin argumentos (error); luego validas que tienes los 3 campos (otro error: el FechaFinal no puede estar relleno) para, finalmente, lanzar una función FechaFinal (otro error: FechaFinal es una variable de tipo fecha, no una función).


La función DiaLabIntl requiere los argumentos FechaInicial y DiasProceso. Los argumentos del tipo de semana o de la tabla de festivos son opcionales. Por defecto toman "0000011" (sábado y domingo no-laborables) y True (aplica la tabla de festivos)

La secuencia de acciones es:
Comprobar que tenemos una fecha inicial y un numero de días --> asignar la fecha final el cálculo

If IsDate(Me!txtFechaInicial) And IsNumeric(Me!txtDiasProceso) Then
  Me!txtFechaFinal = DiaLabIntl(Me!txtFechaInicial, Me!txtDiasProceso)
End If

Un saludo


-------------
Xavi, un minyó de Terrassa

http://www.llodax.com" rel="nofollow - Mi web


Publicado por: maserrano
Fecha de publicación: 30/Mayo/2023 a las 17:32
Vaya, muchas gracias Xavi.
Qué desencaminado estaba.
Lo he probado (por fin) y va perfecto.
Gracias a todos y se puede cerrar la consulta por mi parte



Imprimir página | Cerrar ventana