Rambler's Top100
Форум: MS ACCESSVBVBA MS OfficeMS SQL server
Новые сообщения: 0000

Форум: MS ACCESS

Вопросы связанные с MS ACCESS

Обновить визитку
Участники «Online»
Все участники

 
 

Доброго времени суток, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: вариант с "рабочими днями"
 
 автор: Кабан   (22.04.2009 в 17:10)   личное сообщение
 
 

дана таблица tb_hdays

hdatefrom                hdatetill    Коммент
01.05.2009            03.05.2009    
09.05.2009            10.05.2009    
28.06.2009            29.06.2009    


и функция, которая, глядя в эту таблицу, возвращает следующую рабочую дату. Рабочая дата - это не праздничные,описанные в tb_hdays и не суббота и воскресенье (хотя я бы загнал и их в эту таблицу, но таково было желание жены )


Public Function VDate(dt As Date, Optional turn = 1) As Date
Dim dd As Date, dr As Date, dp&
On Error Resume Next
If Nz(dt, 0) = 0 Then Exit Function
'-- праздник?
If turn = 1 Then
    dd = DLookup("[hdatetill]", "tb_hdays", "" & Format(dt, "\#mm\/dd\/yyyy\#") & " between [hdatefrom] and [hdatetill]")
Else
    dd = DLookup("[hdatefrom]", "tb_hdays", "" & Format(dt, "\#mm\/dd\/yyyy\#") & " between [hdatefrom] and [hdatetill]")
End If
If Nz(dd, 0) <> 0 Then '-- ой, таки праздник!
    dd = DateAdd("d", 1 * turn, dd)
Else
    dd = dt
End If
'--выходной?
dp = DatePart("w", dd, vbUseSystemDayOfWeek)
If dp = 6 Then '--суббота
    If turn = 1 Then
        dd = DateAdd("d", 2, dd)
    Else
        dd = DateAdd("d", -1, dd)
    End If
ElseIf dp = 7 Then '--воскресенье
    If turn = 1 Then
        dd = DateAdd("d", 1, dd)
    Else
        dd = DateAdd("d", -2, dd)
    End If
End If

'--а вдруг еще?!
If turn = 1 Then
    dr = DLookup("[hdatetill]", "tb_hdays", "" & Format(dd, "\#mm\/dd\/yyyy\#") & " between [hdatefrom] and [hdatetill]")
Else
    dr = DLookup("[hdatefrom]", "tb_hdays", "" & Format(dd, "\#mm\/dd\/yyyy\#") & " between [hdatefrom] and [hdatetill]")
End If
If Nz(dr, 0) <> 0 Then '-- ой, таки опять праздник!
    dd = VDate(DateAdd("d", 1 * turn, dr))
End If
VDate = dd
End Function


опция turn - это направление определения след. рабочей даты. если turn=-1, то в обратном направлении, т.е. countdown, по умолчанию - вперёд
функция работает рекурсивно.

использую в запросе такого вида

SELECT tb_projects.pname, tb_jobs.jname, VDate(DateAdd("d",-[n_a_max],[Создание]),-1) AS СрокиСбор, VDate(DateAdd("d",-[n_c_max],[Проверка]),-1) AS Создание, VDate(DateAdd("d",-[n_4_max],[СдатьВПечать]),-1) AS Проверка, VDate(DateAdd("d",-([n_p_max]),[datefrom])) AS СдатьВПечать, [datefrom] & " - " & [datetill] AS СрокиРассылка, tb_work.pid, tb_work.jid
FROM tb_projects INNER JOIN (tb_jobs INNER JOIN tb_work ON tb_jobs.id = tb_work.jid) ON tb_projects.id = tb_work.pid
WHERE (((Month([datefrom]))=[Введите номер месяца]) AND ((Month([datetill]))=[Введите номер месяца]));


для построения графика выполнения проекта
вот... ну , если кому интересно, то можете дорабатывать, использовать

  Ответить  
 
 автор: Lukas   (22.04.2009 в 17:43)   личное сообщение
14 Кб.
 
 

Наверное стоит несколько изменить таблицу исключений, для увеличения функциональности.
Позволит хранить и переносы рабочих дней по Постановлениям правительства.
PS. У нас опять новые веяния с праздниками, чего то опять изменили.

  Ответить  
 
 автор: Кабан   (22.04.2009 в 17:52)   личное сообщение
 
 

та да :) я писал об этом
лиха беда начало ;)

  Ответить  
 
 автор: Lukas   (22.04.2009 в 18:52)   личное сообщение
11 Кб.
 
 

Как-то так:

Public Function funIsWorkDay(datDay As Date) As Boolean
    Dim strFiltr As String
    Dim Except As Integer
    
    strFiltr = "DayExc=" & Day(datDay) & " AND MonthExc=" & Month(datDay) & " AND YearStart<=" & Year(datDay) & " AND (YearEnd>=" & Year(datDay) & " Or YearEnd=0)"
    Except = Nz(DLookup("WorkDay", "tblException", strFiltr), 2)
    Select Case Except
        Case Is = 2
            funIsWorkDay = DatePart("w", datDay, vbUseSystemDayOfWeek) < 6
        Case Else
            funIsWorkDay = Except
    End Select
End Function

Public Function funNextWorkDay(ByVal datDay As Date, Optional blnForvard As Boolean = True, Optional lngShift As Long = 0) As Date
    Dim lngStep As Long
    If blnForvard Then lngStep = 1 Else lngStep = -1
    datDay = datDay + lngStep + lngShift
    Do Until funIsWorkDay(datDay)
        datDay = datDay + lngStep
    Loop
    funNextWorkDay = datDay
End Function

Календаря бумажного нет. Сильно тестить лень.

  Ответить  
 
 автор: Кабан   (22.04.2009 в 18:59)   личное сообщение
 
 

во! не оскудеет Земля на богатырей

  Ответить  
 
 автор: Lukas   (22.04.2009 в 19:02)   личное сообщение
 
 

В том богатыре полтора метра, вместе с кепкой.

Забыл.
Создание индекса по 4 полям в таблице исключений увеличит скорость процентов на 10.

  Ответить  
HiProg.com - Технологии программирования
Rambler's Top100 TopList