1 (изменено: alexii, 2012-07-09 00:23:57)

Тема: VBScript: Вычисление даты

Добрый вечер господа форумчане !!!
Помогите с решением следующей задачи - нужно вычислить дату выдачи заказа по количеству рабочих дней
Есть б/д access с таблицей tblOrders,(Заказы), имеем в ней поля: "Добавлено", "Срок изготовления"(считается в рабочих днях) и "Дата выдачи заказа"...
подсчет ведется с учетом праздников, выходные - Сб, Вс

Для примера: заказ принят 09.07.2012, срок изготовления 21рабочий день, надо найти дату выдачи...( 07.08.2012)

:D:D

2

Re: VBScript: Вычисление даты

Откуда скрипт узнает расписание праздников на все годы?

3

Re: VBScript: Вычисление даты

alexii пишет:

Откуда скрипт узнает расписание праздников на все годы?

Если нужно то можно создать таблицу tblHoliday, где и указывать даты праздников

4

Re: VBScript: Вычисление даты

Несколько нетривиальная задача вычисления количества рабочих дней. Например фраза "приходите через 3 дня", сказанная в понедельник значит "приходите в четверг", а сказанная в пятницу - указывает на среду следующей недели. С учетом разным количеством дней в каждом месяце - число переменных функции увеличивается.

Вряд ли поможет, тем не менее посмотрите на одну из этих функций - возможно она натолкнет Вас на какие-нибудь мысли:


/**
 * Date.prototype.getWorkingDaysInMonth
 *
 * @syntax
 * object.getWorkingDaysInMonth()
 *
 * @description
 * Метод преобразует примитивное значение объекта Date в 
 * количество рабочих дней в месяце. 
 *
 * Ненулевое значение в первом аргументе подразумевает 
 * 6-дневаную неделю (по умолчанию 5 дней в неделе). 
 *
 * Второй параметр - целое число, указывающая количество праздников, 
 * выпадающих на рабочие дни, или функция, которая вычисляет данное 
 * число на основании объекта Date, передаваемого функции. 
 *
 * @param	Integer
 * @param	Callback|Integer
 * @result	Integer
 * @access	public
 */
Date.prototype.getWorkingDaysInMonth = function(longWeek, holidays)
{
	var here = new Date(this.getFullYear(), this.getMonth() + 1, 0);
	var dim = here.getDate();
	var ldm = here.getDay();

	var t = typeof holidays;
	var h = 
		t == 'number' 
		? holidays 
		: t == 'function' 
		? holidays(this) 
		: 0;

	return arguments.callee[longWeek ? 6 : 5][dim][ldm] - h;
};

// Weekday of the last day in month
// Short week - 5 days' week
Date.prototype.getWorkingDaysInMonth[5] = {
	//   Sun Mon Tue Wed Thu Fri Sat
	28: [20, 20, 20, 20, 20, 20, 20],
	29: [20, 21, 21, 21, 21, 21, 20],
	30: [20, 21, 22, 22, 22, 22, 21],
	31: [21, 21, 22, 23, 23, 23, 22]
};

// Long week - 6 days' week
Date.prototype.getWorkingDaysInMonth[6] = {
	//   Sun Mon Tue Wed Thu Fri Sat
	28: [24, 24, 24, 24, 24, 24, 24],
	29: [24, 25, 25, 25, 25, 25, 25],
	30: [25, 25, 26, 26, 26, 26, 26],
	31: [26, 26, 26, 27, 27, 27, 27]
};
( 2 * b ) || ! ( 2 * b )

5

Re: VBScript: Вычисление даты

Тогда пожалуйста:

Option Explicit

Const adOpenStatic     = 3
Const adLockOptimistic = 3

Dim dtStartDate
Dim dtEndDate
Dim lngCount

Dim objConnection
Dim objRecordset

Dim prevLocale


Set objConnection = CreateObject("ADODB.Connection")
Set objRecordset  = CreateObject("ADODB.Recordset")

objConnection.Open "Provider = Microsoft.Jet.OLEDB.4.0; Data Source = 'E:\Песочница\0158\Приложение Microsoft Office Access.mdb'"
objRecordset.Open "SELECT * FROM Holidays", objConnection, adOpenStatic, adLockOptimistic

dtStartDate = CDate("09.07.2012")

WScript.Echo FormatDateTime(dtStartDate, vbLongDate)

dtEndDate = dtStartDate
lngCount = 0

Do Until lngCount >= 21
    dtEndDate = DateAdd("d", 1, dtEndDate)
    
    Select Case WeekdayName(Weekday(dtEndDate))
        Case "суббота", "воскресенье"
            
        Case Else
            prevLocale = SetLocale("en-us")
            objRecordset.Filter = "HolidayDate = #" & dtEndDate & "#"
            SetLocale(prevLocale)
            
            If objRecordset.RecordCount = 0 Then
                lngCount = lngCount + 1
            End If
    End Select
Loop

objRecordset.Close
objConnection.Close

WScript.Echo FormatDateTime(dtEndDate, vbLongDate)

Set objRecordset  = Nothing
Set objConnection = Nothing

WScript.Quit 0

Я создал в базе данных «E:\Песочница\0158\Приложение Microsoft Office Access.mdb» таблицу «Holidays» из двух полей — идентификатор «ID» и дата/время «HolidayDate», добавив в неё для примера подряд пять дней праздников:

ID    HolidayDate
1    20.07.2012
2    21.07.2012
3    22.07.2012
4    23.07.2012
5    24.07.2012

Полученный в итоге результат:

понедельник, 9 июля 2012 года
пятница, 10 августа 2012 года

6

Re: VBScript: Вычисление даты

Спасибо !!!
Но осталось еще пару вопросов...
Насколько я понимаю это код скрипта *.vbs, интересует следующее, а именно как происходит добавление известных параметров в скрипт ???
т.е. у меня есть Б/Д с множеством различных таблиц, включая tblHoliday и tblOrders, в которой имеются поля "Добавлено"- AddTime, "Срок изготовления"- Time(считается в рабочих днях) и "Дата выдачи заказа" - EndTime... и еще много других...
...просто в коде я не знаю где эти поля...

7

Re: VBScript: Вычисление даты

NecroTYN, ничего не понял.

Не используйте повторяющиеся знаки препинания. Сие только ухудшает восприятие.

8 (изменено: NecroTYN, 2012-07-09 15:14:03)

Re: VBScript: Вычисление даты

alexii пишет:

NecroTYN, ничего не понял.

извините, если проще то каким образом передается в скрипт дата приема заказа-09.07.2012 и количество раб. дней-21
просто в таблице еще имеются поля формата Дата

9

Re: VBScript: Вычисление даты

Как сделаете, так и будет передаваться.

У меня есть подозрение, что Вам нужен не VBScript, а VBA. Так?

10

Re: VBScript: Вычисление даты

alexii пишет:

Как сделаете, так и будет передаваться.

а как правильно сделать ??? База данных используется программой написанной на T-SQL - http://www.simple-soft.ru/ProductsCount.htm

alexii пишет:

У меня есть подозрение, что Вам нужен не VBScript, а VBA. Так?

...именно VBScript

11

Re: VBScript: Вычисление даты

Спасибо, ясно.

К сожалению, я не очень представляю себе, как сие можно разумно сделать:

1. В «Значении по умолчанию»/«Условии на значение» для поля автор не даёт возможности использовать такой обычный и типичнейший для Microsoft Access механизм, как вызов пользовательской функции VBA.
2. Вызов скрипта по различным триггерам: триггер срабатывает после смены текущей записи (даже при триггере на изменение поля!).
3. Вызов по кнопке: само поле в форме заполнить нельзя, только таблицу/запрос (и, как тут принято говорить, через жёппу). Форма обновляется когда захочет и если захочет. А может и вовсе не обновиться. Вот так.

Запрет на 1) выглядит очень и очень странным. Либо я «не умею его готовить». Невозможность вызова скрипта в стандартном для WSH варианте «/Поле:[Поле]», а только и исключительно в нелепом виде «/[Поле]» выглядит и вовсе полной ахинеей.

В общем, наименьшее из зол таково:

Option Explicit

Const adOpenStatic     = 3
Const adLockOptimistic = 3

Dim strDatabase
Dim lngID

Dim objFSO
Dim objConnection
Dim objRecordset

Dim dtStartDate
Dim dtEndDate
Dim lngCount

Dim prevLocale


If WScript.Arguments.Count = 2 Then
    strDatabase = Mid(WScript.Arguments.Item(0), 2)
    lngID = Mid(WScript.Arguments.Item(1), 2)
    
    Set objFSO        = WScript.CreateObject("Scripting.FileSystemObject")
    Set objConnection = WScript.CreateObject("ADODB.Connection")
    Set objRecordset  = WScript.CreateObject("ADODB.Recordset")
    
    If objFSO.FileExists(strDatabase) Then
        objConnection.Open "Provider = Microsoft.Jet.OLEDB.4.0; " & _
            "Data Source = '" & strDatabase & "'"
        
        With objRecordset
            .Open "SELECT * FROM qdfOrders WHERE ID = " & CStr(lngID) & "", objConnection, adOpenStatic, adLockOptimistic
            dtStartDate = CDate(.Fields.Item("OrderDate").Value)
            .Close
            
            .Open "SELECT * FROM tblHolidays", objConnection, adOpenStatic, adLockOptimistic
            
            dtEndDate = dtStartDate
            lngCount = 0
            
            Do Until lngCount >= 21
                dtEndDate = DateAdd("d", 1, dtEndDate)
                
                Select Case WeekdayName(Weekday(dtEndDate))
                    Case "суббота", "воскресенье"
                    
                    Case Else
                        prevLocale = SetLocale("en-us")
                        .Filter = "HolidayDate = #" & dtEndDate & "#"
                        SetLocale(prevLocale)
                        
                        If .RecordCount = 0 Then
                            lngCount = lngCount + 1
                        End If
                End Select
            Loop
            
            .Close
        End With
        
        prevLocale = SetLocale("en-us")
        objConnection.Execute "UPDATE qdfOrders SET DoneDate = #" & dtEndDate & "# WHERE ID = " & CStr(lngID) & ""
        SetLocale(prevLocale)
        
        objConnection.Close
    Else
        WScript.Echo "Database file [" & strDatabase & "] not found"
    End If
    
    Set objRecordset  = Nothing
    Set objConnection = Nothing
    Set objFSO        = Nothing
Else
    WScript.Echo "Usage from toolbar on [Склад и торговля]:"
    WScript.Echo "" & WScript.ScriptName & " /[CurrentDB] /[ID]"
End If

WScript.Quit 0

Вызов скрипта вешаете на кнопку на панели инструментов для формы «Заказы» в виде:

<Путь>\Имя скрипта.vbs /[CurrentDB] /[ID]

где «<Путь>\Имя скрипта» — путь и имя к сохранённому скрипту. Задали «Дату заказа» — нажали кнопку. И молитесь, чтобы форма обновилась.

Таблица «tblHolidays» аналогична по формату выше описанной. Создаёте её в базе данных «.mdb» «Склад и торговля» и заполняете ручками. Алгоритм, по-хорошему, надо менять: сейчас никак не учитывается возможный перенос выходных дней с субботы и воскресенья на будние дни по решению «больших голов». Может быть, сделать так:

1. Заполняем «tblHolidays» списком суббот, воскресений, известных праздников N-ного года.
2. Посему из алгоритма выкидываем проверку на субботы и воскресенья.
3. Выправление заполненного списка до реальности (перенос выходных дней с субботы и воскресенья на будние дни) оставляем на совести оператора.

12 (изменено: NecroTYN, 2012-07-14 16:37:37)

Re: VBScript: Вычисление даты

alexii пишет:

Вызов скрипта вешаете на кнопку на панели инструментов для формы «Заказы» в виде:

Вызов скрипта можно повесить на "При добавлении и изменении записи" для поля "AddTime"... через меню "Триггеры"
Параметр "количество рабочих дней" тоже не постоянный и меняется оператором - правда не очень часто

...а если предположить такую схему работы:
вводим сначала раб. дни, затем ставим дату, жмем "ок" на форме. Дальше должно происходить так: запускается скрипт, берется кол-во раб. дней и дата, все это обрабатывается и выдается результат в поле AddTime

alexii пишет:

не учитывается возможный перенос выходных дней с субботы и воскресенья на будние дни по решению «больших голов». Может быть, сделать так:

Думаю можно и так

?????

13 (изменено: NecroTYN, 2012-07-16 16:41:44)

Re: VBScript: Вычисление даты

alexii
В вышеприведенном вами коде срок изготовления является неизменным, а нужно сделать чтоб менялся оператором в поле "Time" of qdfOrders...
?????

14

Re: VBScript: Вычисление даты

Вызов скрипта можно повесить на "При добавлении и изменении записи" для поля "AddTime"... через меню "Триггеры"

А чем сие поможет? Насколько я понял, данный триггер срабатывает, когда мы покидаем запись.

Параметр "количество рабочих дней" тоже не постоянный и меняется оператором - правда не очень часто

Что это за параметр? Где он находится?

...а если предположить такую схему работы:
вводим сначала раб. дни, затем ставим дату, жмем "ок" на форме.

Не очень представляю себе, как это может выглядеть.

В вышеприведенном вами коде срок изготовления является неизменным, а нужно сделать чтоб менялся оператором в поле "Time" of qdfOrders...

Попробую посмотреть.

15 (изменено: NecroTYN, 2012-07-18 23:48:20)

Re: VBScript: Вычисление даты

Второй и четвертый пункт - это одно и то же

А чем сие поможет? Насколько я понял, данный триггер срабатывает, когда мы покидаем запись.

покидаем или изменяем, насколько я понял прога хватает последние введенные значения

Не очень представляю себе, как это может выглядеть.

так и выглядит, сначала заполняем форму, при нажатии "ОК" срабатывает тригер на запуск скрипта, который в свою очередь берет из указанных нами полей и таблиц нужные ему данные... Триггер срабатывает после ввода данных

16

Re: VBScript: Вычисление даты

Люди грамотные, помогите пожалуйста - ну очень надо !!!

17

Re: VBScript: Вычисление даты

alexii пишет:

Попробую посмотреть.

alexii посмотрите пожалуйста

18 (изменено: NecroTYN, 2012-07-29 13:04:43)

Re: VBScript: Вычисление даты

alexii
посмотрите пожалуйста, сделали вот такой код:

' 1) количество рабочих дней читается из таблицы Б/Д - qdfOrders поле "ExecutionTime", тип целое.
' 2) выходные и праздничные дни - в таблице tblHolidays, заполение на совести оператора.

Option Explicit

Const adOpenStatic     = 3
Const adLockOptimistic = 3

Dim strDatabase
Dim lngID

Dim objFSO
Dim objConnection
Dim objRecordset

Dim dtStartDate
Dim dtEndDate
Dim lngCount

Dim prevLocale


If WScript.Arguments.Count = 2 Then
    strDatabase = Mid(WScript.Arguments(0), 2)
    lngID = Mid(WScript.Arguments(1), 2)
    
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    
    If objFSO.FileExists(strDatabase) Then
        prevLocale = SetLocale()
        SetLocale("en-us")
        Set objConnection = CreateObject("ADODB.Connection")
        Set objRecordset  = CreateObject("ADODB.Recordset")
        objConnection.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="& strDatabase &";"
        
        With objRecordset
            .Open "SELECT * FROM qdfOrders WHERE ID = " & lngID & "", objConnection, adOpenStatic, adLockOptimistic
            dtStartDate = .Fields("OrderDate").Value
        lngCount    = .Fields("ExecutionTime").Value 
        .Close
            
            .Open _
                "SELECT * FROM tblHolidays"& _
                " WHERE HolidayDate BETWEEN #"& dtStartDate &"#"& _
                " AND #"& DateAdd("d", lngCount*2+1, dtStartDate) &"#", _
                objConnection, adOpenStatic, adLockOptimistic
            
            dtEndDate = DateAdd("d", lngCount, dtStartDate)
            
            .Filter  = "HolidayDate>=#"& dtStartDate &"# AND HolidayDate<=#"& dtEndDate &"#" 
            lngCount = .RecordCount
            
            Do While lngCount>0
                dtStartDate = DateAdd("d", 1, dtEndDate)
                dtEndDate   = DateAdd("d", lngCount, dtEndDate)
                .Filter  = "HolidayDate>=#"& dtStartDate &"# AND HolidayDate<=#"& dtEndDate &"#"
                lngCount = .RecordCount
            Loop
            
            .Close
        End With
        
        objConnection.Execute "UPDATE qdfOrders SET DoneDate=#" & dtEndDate & "# WHERE ID=" & lngID
        
        objConnection.Close
        Set objRecordset  = Nothing
        Set objConnection = Nothing
        SetLocale(prevLocale)
    Else
        WScript.Echo "Database file [" & strDatabase & "] not found"
    End If
    
    Set objFSO = Nothing
Else
    WScript.Echo "Usage from toolbar on [Склад и торговля]:"
    WScript.Echo "" & WScript.ScriptName & " /[CurrentDB] /[ID]"
End If

WScript.Quit 0

не сработал...
Поле "Time" переименовал в "ExecutionTime"
пробовал вешать исполнение как на отдельную кнопку, так и на условие для поля таблицы...