2011-01-06 41 views
0

私はアクセス2007を使用しています。ライブラリシステムとして動作するようにデータベースを設定しようとしていますが、14日後に自動的に日付を計算する関数が必要です日付すなわちローン日付と期日。しかし、図書館は特定の日にのみ開かれています。だから私は、週末や学校の休日のような時間外の日付を含めない14日間が必要ですSQLを使用して特定の日付範囲内の日付を計算する

私はSelect CaseまたはIIFを使用する必要があると思いますか?

ご了承ください。

おかげ

デビッド

答えて

0

私は非常によく似た問題を抱えていたし、Remouと共同で提案した方法でそれを解決しました。

私が使用したコードは、いくつかのMicrosoftコードの修正版です。必要なのは、「tblNon_working_days」というテーブルで、数えてはならないすべての日を含みます。

Option Compare Database 
Option Explicit 

' ********* Code Start ************** 
' 
' Modified from code in 
' "Visual Basic Language Developer's Handbook" 
' by Ken Getz and Mike Gilbert 
' Copyright 2000; Sybex, Inc. All rights reserved. 
' 

Public Function dhAddWorkDaysA(lngDays As Long, Optional dtmDate As Date = 0) 
'Optional adtmDates As Variant) As Date 
    ' Add the specified number of work days to the 
    ' specified date. 

    ' Modified from code in 
    ' "Visual Basic Language Developer's Handbook" 
    ' by Ken Getz and Mike Gilbert 
    ' Copyright 2000; Sybex, Inc. All rights reserved. 

    ' In: 
    ' lngDays: 
    '  Number of work days to add to the start date. 
    ' dtmDate: 
    '  date on which to start looking. 
    '  Use the current date, if none was specified. 
    ' adtmDates (Optional): 
    '  Array containing holiday dates. Can also be a single 
    '  date value, if that's what you want. 
    ' Out: 
    ' Return Value: 
    '  The date of the working day lngDays from the start, taking 
    '  into account weekends and holidays. 
    ' Example: 
    ' dhAddWorkDaysA(10, #2/9/2000#, Array(#2/16/2000#, #2/17/2000#)) 
    ' returns #2/25/2000#, which is the date 10 work days 
    ' after 2/9/2000, if you treat 2/16 and 2/17 as holidays 
    ' (just made-up holidays, for example purposes only). 

    ' Did the caller pass in a date? If not, use 
    ' the current date. 
    Dim lngCount As Long 
    Dim dtmTemp As Date 
    Dim adtmDates() As Variant 

    'loadup the adtmDates with all the records from the table tblNon_working_days 

    Dim rst As DAO.Recordset 
    Dim i As Long 

    Set rst = DBEngine(0)(0).OpenRecordset("SELECT Date FROM tblNon_working_days", dbOpenForwardOnly) 
    With rst 
     If .RecordCount > 0 Then 
      i = 1 
      Do Until .EOF 
       ReDim Preserve adtmDates(i) 
       adtmDates(i) = !Date 
       .MoveNext 
       i = i + 1 
      Loop 
     End If 
    End With 

    rst.Close 

    Set rst = Nothing 

    If dtmDate = 0 Then 
     dtmDate = Date 
    End If 

    dtmTemp = dtmDate 
    For lngCount = 1 To lngDays 
     dtmTemp = dhNextWorkdayA(dtmTemp, adtmDates) 
    Next lngCount 
    dhAddWorkDaysA = dtmTemp 
End Function 

Public Function dhNextWorkdayA(_ 
Optional dtmDate As Date = 0, _ 
Optional adtmDates As Variant = Empty) As Date 

    ' Return the next working day after the specified date. 

    ' Modified from code in 
    ' "Visual Basic Language Developer's Handbook" 
    ' by Ken Getz and Mike Gilbert 
    ' Copyright 2000; Sybex, Inc. All rights reserved. 

    ' Requires: 
    ' SkipHolidays 
    ' IsWeekend 

    ' In: 
    ' dtmDate: 
    '  date on which to start looking. 
    '  Use the current date, if none was specified. 
    ' adtmDates (Optional): 
    '  Array containing holiday dates. Can also be a single 
    '  date value. 
    ' Out: 
    ' Return Value: 
    '  The date of the next working day, taking 
    '  into account weekends and holidays. 
    ' Example: 
    ' ' Find the next working date after 5/30/97 
    ' dtmDate = dhNextWorkdayA(#5/23/1997#, #5/26/97#) 
    ' ' dtmDate should be 5/27/97, because 5/26/97 is Memorial day. 

    ' Did the caller pass in a date? If not, use 
    ' the current date. 
    If dtmDate = 0 Then 
     dtmDate = Date 
    End If 

    dhNextWorkdayA = SkipHolidaysA(adtmDates, dtmDate + 1, 1) 
End Function 

Public Function dhPreviousWorkdayA(_ 
Optional dtmDate As Date = 0, _ 
Optional adtmDates As Variant = Empty) As Date 

    ' Return the previous working day before the specified date. 

    ' Modified from code in 
    ' "Visual Basic Language Developer's Handbook" 
    ' by Ken Getz and Mike Gilbert 
    ' Copyright 2000; Sybex, Inc. All rights reserved. 

    ' Requires: 
    ' SkipHolidays 
    ' IsWeekend 

    ' In: 
    ' dtmDate: 
    '  date on which to start looking. 
    '  Use the current date, if none was specified. 
    ' adtmDates (Optional): 
    '  Array containing holiday dates. Can also be a single 
    '  date value. 
    ' Out: 
    ' Return Value: 
    '  The date of the previous working day, taking 
    '  into account weekends and holidays. 
    ' Example: 
    ' ' Find the next working date before 1/1/2000 

    ' dtmDate = dhPreviousWorkdayA(#1/1/2000#, Array(#12/31/1999#, #1/1/2000#)) 
    ' ' dtmDate should be 12/30/1999, because of the New Year's holidays. 

    ' Did the caller pass in a date? If not, use 
    ' the current date. 
    If dtmDate = 0 Then 
     dtmDate = Date 
    End If 

    dhPreviousWorkdayA = SkipHolidaysA(adtmDates, dtmDate - 1, -1) 
End Function 

Public Function dhFirstWorkdayInMonthA(_ 
Optional dtmDate As Date = 0, _ 
Optional adtmDates As Variant = Empty) As Date 

    ' Return the first working day in the month specified. 

    ' Modified from code in 
    ' "Visual Basic Language Developer's Handbook" 
    ' by Ken Getz and Mike Gilbert 
    ' Copyright 2000; Sybex, Inc. All rights reserved. 

    ' Requires: 
    ' SkipHolidays 
    ' IsWeekend 

    ' In: 
    ' dtmDate: 
    '  date within the month of interest. 
    '  Use the current date, if none was specified. 
    ' adtmDates (Optional): 
    '  Array containing holiday dates. Can also be a single 
    '  date value. 
    ' Out: 
    ' Return Value: 
    '  The date of the first working day in the month, taking 
    '  into account weekends and holidays. 
    ' Example: 
    ' ' Find the first working day in 1999 
    ' dtmDate = dhFirstWorkdayInMonthA(#1/1/1999#, #1/1/1999#) 

    Dim dtmTemp As Date 

    ' Did the caller pass in a date? If not, use 
    ' the current date. 
    If dtmDate = 0 Then 
     dtmDate = Date 
    End If 

    dtmTemp = DateSerial(Year(dtmDate), Month(dtmDate), 1) 
    dhFirstWorkdayInMonthA = SkipHolidaysA(adtmDates, dtmTemp, 1) 
End Function 

Public Function dhLastWorkdayInMonthA(_ 
Optional dtmDate As Date = 0, _ 
Optional adtmDates As Variant = Empty) As Date 

    ' Return the last working day in the month specified. 

    ' Modified from code in 
    ' "Visual Basic Language Developer's Handbook" 
    ' by Ken Getz and Mike Gilbert 
    ' Copyright 2000; Sybex, Inc. All rights reserved. 

    ' Requires: 
    ' SkipHolidays 
    ' IsWeekend 

    ' In: 
    ' dtmDate: 
    '  date within the month of interest. 
    '  Use the current date, if none was specified. 
    ' adtmDates (Optional): 
    '  Array containing holiday dates. Can also be a single 
    '  date value. 
    ' Out: 
    ' Return Value: 
    '  The date of the last working day in the month, taking 
    '  into account weekends and holidays. 
    ' Example: 
    ' ' Find the last working day in 1999 
    ' dtmDate = dhLastWorkdayInMonthA(#12/1/1999#, #12/31/1999#) 

    Dim dtmTemp As Date 

    ' Did the caller pass in a date? If not, use 
    ' the current date. 
    If dtmDate = 0 Then 
     dtmDate = Date 
    End If 

    dtmTemp = DateSerial(Year(dtmDate), Month(dtmDate) + 1, 0) 
    dhLastWorkdayInMonthA = SkipHolidaysA(adtmDates, dtmTemp, -1) 
End Function 

Public Function dhCountWorkdaysA(ByVal dtmStart As Date, ByVal dtmEnd As Date, _ 
Optional adtmDates As Variant = Empty) _ 
As Integer 

    ' Count the business days (not counting weekends/holidays) in 
    ' a given date range. 

    ' Modified from code in 
    ' "Visual Basic Language Developer's Handbook" 
    ' by Ken Getz and Mike Gilbert 
    ' Copyright 2000; Sybex, Inc. All rights reserved. 

    ' Requires: 
    ' SkipHolidays 
    ' CountHolidays 
    ' IsWeekend 

    ' In: 
    ' dtmStart: 
    '  Date specifying the start of the range (inclusive) 
    ' dtmEnd: 
    '  Date specifying the end of the range (inclusive) 
    '  (dates will be swapped if out of order) 
    ' adtmDates (Optional): 
    '  Array containing holiday dates. Can also be a single 
    '  date value. 
    ' Out: 
    ' Return Value: 
    '  Number of working days (not counting weekends and optionally, holidays) 
    '  in the specified range. 
    ' Example: 
    ' Debug.Print dhCountWorkdaysA(#7/2/2000#, #7/5/2000#, _ 
    ' Array(#1/1/2000#, #7/4/2000#)) 
    ' 
    ' returns 2, because 7/2/2000 is Sunday, 7/4/2000 is a holiday, 
    ' leaving 7/3 and 7/5 as workdays. 

    Dim intDays As Integer 
    Dim dtmTemp As Date 
    Dim intSubtract As Integer 

    ' Swap the dates if necessary.> 
    If dtmEnd < dtmStart Then 
     dtmTemp = dtmStart 
     dtmStart = dtmEnd 
     dtmEnd = dtmTemp 
    End If 

    ' Get the start and end dates to be weekdays. 
    dtmStart = SkipHolidaysA(adtmDates, dtmStart, 1) 
    dtmEnd = SkipHolidaysA(adtmDates, dtmEnd, -1) 
    If dtmStart > dtmEnd Then 
     ' Sorry, no Workdays to be had. Just return 0. 
     dhCountWorkdaysA = 0 
    Else 
     intDays = dtmEnd - dtmStart + 1 

     ' Subtract off weekend days. Do this by figuring out how 
     ' many calendar weeks there are between the dates, and 
     ' multiplying the difference by two (because there are two 
     ' weekend days for each week). That is, if the difference 
     ' is 0, the two days are in the same week. If the 
     ' difference is 1, then we have two weekend days. 
     intSubtract = (DateDiff("ww", dtmStart, dtmEnd) * 2) 

     ' The answer to our quest is all the weekdays, minus any 
     ' holidays found in the table. 
     intSubtract = intSubtract + _ 
     CountHolidaysA(adtmDates, dtmStart, dtmEnd) 

     dhCountWorkdaysA = intDays - intSubtract 
    End If 
End Function 

Private Function CountHolidaysA(_ 
adtmDates As Variant, _ 
dtmStart As Date, dtmEnd As Date) As Long 

    ' Count holidays between two end dates. 
    ' 
    ' Modified from code in 
    ' "Visual Basic Language Developer's Handbook" 
    ' by Ken Getz and Mike Gilbert 
    ' Copyright 2000; Sybex, Inc. All rights reserved. 

    ' Required by: 
    ' dhCountWorkdays 

    ' Requires: 
    ' IsWeekend 


    Dim lngItem As Long 
    Dim lngCount As Long 
    Dim blnFound As Long 
    Dim dtmTemp As Date 

    On Error GoTo HandleErr 
    lngCount = 0 
    Select Case VarType(adtmDates) 
     Case vbArray + vbDate, vbArray + vbVariant 
      ' You got an array of variants, or of dates. 
      ' Loop through, looking for non-weekend values 
      ' between the two endpoints. 
      For lngItem = LBound(adtmDates) To UBound(adtmDates) 
       dtmTemp = adtmDates(lngItem) 
       If dtmTemp >= dtmStart And dtmTemp <= dtmEnd Then 
        If Not IsWeekend(dtmTemp) Then 
         lngCount = lngCount + 1 
        End If 
       End If 
      Next lngItem 
     Case vbDate 
      ' You got one date. So see if it's a non-weekend 
      ' date between the two endpoints. 
      If adtmDates >= dtmStart And adtmDates <= dtmEnd Then 
       If Not IsWeekend(adtmDates) Then 
        lngCount = 1 
       End If 
      End If 
    End Select 

ExitHere: 
    CountHolidaysA = lngCount 
    Exit Function 

HandleErr: 
    ' No matter what the error, just 
    ' return without complaining. 
    ' The worst that could happen is that the code 
    ' include a holiday as a real day, even if 
    ' it's in the table. 
    Resume ExitHere 
End Function 

Private Function FindItemInArray(varItemToFind As Variant, _ 
avarItemsToSearch As Variant) As Boolean 
    Dim lngItem As Long 

    On Error GoTo HandleErrors 

    For lngItem = LBound(avarItemsToSearch) To UBound(avarItemsToSearch) 
     If avarItemsToSearch(lngItem) = varItemToFind Then 
      FindItemInArray = True 
      GoTo ExitHere 
     End If 
    Next lngItem 

ExitHere: 
    Exit Function 

HandleErrors: 
    ' Do nothing at all. 
    ' Return False. 
    Resume ExitHere 
End Function 

Private Function IsWeekend(dtmTemp As Variant) As Boolean 
    ' If your weekends aren't Saturday (day 7) and Sunday (day 1), 
    ' change this routine to return True for whatever days 
    ' you DO treat as weekend days. 

    ' Modified from code in "Visual Basic Language Developer's Handbook" 
    ' by Ken Getz and Mike Gilbert 
    ' Copyright 2000; Sybex, Inc. All rights reserved. 

    ' Required by: 
    ' SkipHolidays 
    ' dhFirstWorkdayInMonth 
    ' dbLastWorkdayInMonth 
    ' dhNextWorkday 
    ' dhPreviousWorkday 
    ' dhCountWorkdays 

    If VarType(dtmTemp) = vbDate Then 
     Select Case WeekDay(dtmTemp) 
      Case vbSaturday, vbSunday 
       IsWeekend = True 
      Case Else 
       IsWeekend = False 
     End Select 
    End If 
End Function 

Private Function SkipHolidaysA(_ 
adtmDates As Variant, _ 
dtmTemp As Date, intIncrement As Integer) As Date 
    ' Skip weekend days, and holidays in the array referred to by adtmDates. 
    ' Return dtmTemp + as many days as it takes to get to a day that's not 
    ' a holiday or weekend. 

    ' Modified from code in 
    ' "Visual Basic Language Developer's Handbook" 
    ' by Ken Getz and Mike Gilbert 
    ' Copyright 2000; Sybex, Inc. All rights reserved. 

    ' Required by: 
    ' dhFirstWorkdayInMonthA 
    ' dbLastWorkdayInMonthA 
    ' dhNextWorkdayA 
    ' dhPreviousWorkdayA 
    ' dhCountWorkdaysA 

    ' Requires: 
    ' IsWeekend 

    Dim strCriteria As String 
    Dim strFieldName As String 
    Dim lngItem As Long 
    Dim blnFound As Boolean 

    On Error GoTo HandleErrors 

    ' Move up to the first Monday/last Friday, if the first/last 
    ' of the month was a weekend date. Then skip holidays. 
    ' Repeat this entire process until you get to a weekday. 
    ' Unless adtmDates an item for every day in the year (!) 
    ' this should finally converge on a weekday. 

    Do 
     Do While IsWeekend(dtmTemp) 
      dtmTemp = dtmTemp + intIncrement 
     Loop 
     Select Case VarType(adtmDates) 
      Case vbArray + vbDate, vbArray + vbVariant 
       Do 
        blnFound = FindItemInArray(dtmTemp, adtmDates) 
        If blnFound Then 
         dtmTemp = dtmTemp + intIncrement 
        End If 
       Loop Until Not blnFound 
      Case vbDate 
       If dtmTemp = adtmDates Then 
        dtmTemp = dtmTemp + intIncrement 
       End If 
     End Select 
    Loop Until Not IsWeekend(dtmTemp) 

ExitHere: 
    SkipHolidaysA = dtmTemp 
    Exit Function 

HandleErrors: 
    ' No matter what the error, just 
    ' return without complaining. 
    ' The worst that could happen is that we 
    ' include a holiday as a real day, even if 
    ' it's in the array. 
    Resume ExitHere 

End Function 
0

一つの方法は、有効な日付を格納する表を作成し、期日を計算助けるためにそれを使用することです。そうすれば、来年、学校は1月18日を新しい休日にすることに決めます。コードを修正するのではなく、テーブルから行を削除するだけです。

関連する問題