1с получить количество рабочих дней
Обновлено: 05.07.2024
1. делением на продолжительность рабочего дня не подходит, т.к. каждый день разное количество часов,
2. Запросом собрать фактически отработанные периоды, а потом выяснять в какие дни были не нулевые показания часов - ужасно не "красиво"
ЗаполнениеДокументов.ЧислоРабочихДней(ДатаНачало, ДатаОкончание) в egg
(0) Есть такая задачка на спеца по платформе: решается созданием 2х регистров расчета, и соответсвенно у РС ГрафикиРаботы - 2 ресурса - первый в днях, второй в часах.
(7) миздец, очередная нетленка. смелые люди - пишут расчет и в ЗУП не глядят.
(5) к сожалению УПП у меня нет и быстро скачать возможности нет.
(8) Вести дополнительный регистр только для того, что бы считать количество дней? Хм. это можно обдумать. Спасибо.
(9) в ЗУПе я не в ЗУБ ногой :(, не архитектуры не знаю и времени в настоящий момент нет разбирать тысячестроковые коды. Я думал, что мой вопрос прост и алгоритм решения здесь подскажут (сам на форуме ни чего не нашел).
Получаеться что запрос это единственное решение без увеличения объектов метаданных?
(11) написано же, еще один ресурс делаешь и заполняешь.
>>Получаеться что запрос это единственное решение без увеличения объектов метаданных?
а потом тебе в по базе за 3 месяца такие данные нужны будут? Очередно запрос сочинять?
>>Вести дополнительный регистр только для того, что бы считать количество дней?
нахер он не нужен.
(12) С ресурсом не совсем понятно :
Ресурс - ресурс где?
если в Регистре расчетов, так у меня они там уже есть Дней и часов.
вопрос в том, как корректней заполнить ресурс Дней?
если в регистре сведений "Графики" тогда вопрос, как его обрабатывать?
(13) в регистре расчетов естественно.
>>вопрос в том, как корректней заполнить ресурс Дней?
этого никто кроме вас не знает, раз количество часов каждый день разное
Rom Написал:
-------------------------------------------------------
> Подскажите, как посчитать количество РАБОЧИХ дней
> между 2мя датами?
> Из помощника, понял что нужно использовать:
> Дней(дата1, дата2); и УчитыватьПраздники(); но как
> их в модуль списока справочника вставить, чтобы
> считал?
> Праздниками считаются все красные даты? и выходные
> тоже?
По-моему, в типовых д.б. так называемые календари, где уже отмечены и выходные и праздники - покопай в этом направлении.
дайте ссылку где можно про календари почитать, а то в моей книжке про них нислова не сказано.
Процедура РабДни()
перем Дни;
Календ = СоздатьОбъект(Календари.Служащие);
Дни = Календ.Дней( ДатаУвольнения, ДатаПриема);
Сообщить(Дни);
КонецПроцедуры
Календ = СоздатьОбъект(Календари.Служащие);
: Неудачная попытка создания объекта
-------------------------------------------------------
> Процедура РабДни()
> перем Дни;
> Календ = СоздатьОбъект(Календари.Служащие);
> Дни = Календ.Дней( ДатаУвольнения,
> ДатаПриема);
> Сообщить(Дни);
> КонецПроцедуры
>
> пишет ERR
>
> Календ = СоздатьОбъект(Календари.Служащие);
> > уль(3)>: Неудачная попытка создания объекта
>
> почему?
Во-первых, сразу бросается в глаза:
Календ = СоздатьОбъект(Календари.Служащие);
надо хотя бы уж
Календ = СоздатьОбъект("Календарь.Служащие");
В справке 1С по календарям не густо. Достань к-нить типовуху и посмотри, как там сделано.
Цитата:
Объект Календарь в системе 1С:Предприятие предназначен для вычисления временных интервалов на основании произвольных временных графиков. Этот объект может использоваться, например, для учета графика работы предприятия, графика работы внешних организаций, графика учета рабочего времени тех или иных работников предприятия и пр.
Календарь представляет собой объект, который устанавливает для каждой календарной даты некоторое числовое значение, которое может интерпретироваться при работе программы тем или иным образом. Например, в календаре, представляющем собой график работы организации или предприятия, каждому рабочему дню может соответствовать единица, а каждому выходному — ноль. В календаре учета рабочего времени сотрудников предприятия, каждой дате календаря может соответствовать число — продолжительность рабочего дня в часах и т. д.
В глобальном контексте программы 1С:Предприятие есть атрибут "Календари". Этот объект в качестве своих атрибутов имеет значения объектов конкретных видов календарей, заданных в конфигурации. Кроме того, этот объект имеет метод ПолучитьАтрибут, который позволяет получить доступ к объекту календаря конкретного вида по его имени. Т.е. допустимы следующие синтаксические конструкции:
Календари.Служащие.Дней(ТекДата, ТекДата + 5);
Календари.ПолучитьАтрибут("Служащие").Дней(ТекДата, ТекДата + 5);
Праздники в системе 1С:Предприятие представляет собой объект похожий на календарь, но он заполняется выборочно (не все даты подряд) и в нем могут вводиться и удаляться строки для определенных дат. Данный объект используются как набор исключений при заполнении календарей (см. метод календаря УчитыватьПраздники).
Работа с производственными календарями, рабочими графиками часто встречается в практике разработки. Большинство задач можно свести к двум: 1) Добавить к дате (отнять от даты) некоторое количество рабочих дней и 2) найти разницу в рабочих днях между двумя датами. Несмотря на кажущуюся простоту, в этих задачах достаточно подводных камней, как методических, так и технологических. Естественно эта тема не была обойдена вниманием разработчиков типовых конфигураций и членов нашего сообщества. Простой поиск дает несколько результатов:
На мой взгляд, предлагаемые решения обладают теми или иными недостатками. В их числе:
- сложность полученных запросов: применение временных таблиц, использование группировок больших таблиц, получаемых в результате соединения
- не все решения хорошо работает с некоторыми входными данными, например в качестве входных параметров-дат могут быть использованы выходные дни
- некоторые решения предполагают дополнительную обработку программным кодом промежуточных данных, полученных в результате запроса
- часто решается узкая задача, т.е. решение не универсально.
Предлагаю свой вариант решения.
Постановка задачи:
Предположим, на предприятии ведется учет выполняемых работ. Каждая работа выполняется целое число дней, всегда начинается в начале дня, а заканчивается через несколько дней в конце дня. Продолжительность работ может быть от 1 дня, до нескольких лет (важность условия этого будет упомянута ниже). Необходимо иметь инструмент, позволяющий выполнять расчеты дат начала, окончания работ, продолжительностей работ, временных промежутков между работами. Все расчеты выполнять в рабочих днях. Решение должно позволять использование его в запросах.
В чем могут быть "подводные камни" при решении? Например токарь работает по стандартному рабочему графику - пятидневке. 01 апреля 2019 он начинает изготавливать деталь №1, тратит на ее изготовление 5 дней, и начинает изготавливать следующую деталь №2. Когда он закончит изготовление детали №1? Когда начнет изготавливать деталь №2? Казалось бы в обоих случаях ответ: через 5 рабочих дней после 01 апреля, т.е. к 01.04.2019 надо прибавить 5 рабочих дней. Но в первом случае ответ - 05.04.2019, а во втором - 08.04.2019.
Решение:
Решение поставленной задачи неожиданно получилось довольно простым.
Для учета рабочих графиков (производственных календарей) используем вспомогательный регистр сведений:
РабочийГрафик - ссылка на справочник "РабочиеГрафики" - если на предприятии используется несколько графиков (пятидневка, пятидневка с праздниками, семидневка и т.п.)
Дата - дата графика (без времени)
ЭтоРабочийДень - флаг рабочий/нерабочий день
КолВоДнейСНачалаПериода - Число рабочих дней, прошедших до начала даты записи, начиная с определенной, наперед заданной даты. В моем примере используется 01.01.2000.
Регистр необходимо заполнить на весь период, в пределах которого будут производится расчеты.
Теперь для нахождения разницы дат нам надо в регистре найти два числа, соответствующие этим датам и определить их разницу. Для добавления к дате некоторого числа рабочих дней, надо в регистре найти соответствующее дате число, добавить к нему число рабочих дней, и по результату найти в регистре соответствующую дату рабочего дня. Осталось учесть упомянутые выше сложности и получим следующее:
Примеры использования
Как видим запросы получаются довольно простыми, не используются ни временные таблицы, ни группировки с агрегатными функциями, ни постобработка. Ничего не мешает производить расчет в запросе для нескольких записей. В прилагаемом файле реализован пример отчета по выполненным работам: дана дата начала, предполагаемая плановая продолжительность работы и фактическая дата завершения, определяется плановая дата завершения и отставание факта от плана.
Может возникнуть вопрос: оправдано ли с точки зрения производительности использование дополнительного регистра такой структуры, ведь при изменении флага рабочего/выходного дня надо пересчитывать все записи с большей датой? Я считаю, что вполне. Во-первых, изменение производственного календаря происходит обычно не чаще одного раза в месяц, а полный пересчет и сохранение набора записей за 100 лет(
40000 записей) по выбранному графику занимает считанные секунды. А во-вторых, выгода от использования быстрого массового расчета как правило с лихвой перекроет все время, потраченное на предварительную подготовку.
А что же БСП?
Опытный разработчик, использующий БСП, может сказать: "Так ведь в БСП реализовано почти что то же самое!". Да, действительно в БСП есть аналогичный регистр:
Есть также программный интерфейс модулей "ГрафикиРаботы", "КалендарныеГрафики" с функциями "РазностьДатПоКалендарю", "ДатыПоГрафику" и т.п. Но если присмотреться, то можно увидеть, что в регистре имеется измерение "Год". То есть в этом регистре отсчет количества дней идет с начала каждого года. Когда мы работаем с датами в пределах одного года, то подход при расчете совпадает с рассмотренным. Но если даты попадают в разные года, а особенно если рассматривается промежуток в несколько лет, то алгоритм получается весьма сложным. Все интересующиеся могут самостоятельно сравнить объем программного кода в библиотеке и в предложенном решении. Скорее всего, разработчики БСП стремились к упрощению процедуры заполнения - каждый год рабочего графика заполняется отдельно и не зависит от других. Но в результате мы получаем существенное усложнение алгоритмов при решении практических задач. Я бы рекомендовал использовать регистры БСП как источник для заполнения регистра "РабочиеДни", а все дальнейшие операции производить уже с ним.
UPD 25.06.2019:
Для конфигураций с БСП добавлено заполнение регистра на основе данных из типовых объектов - регистра КалендарныеГрафики и справочника Календари. В процессе обработки заполняется регистр за период с 2000 г. по примерно 2109 г. - 40000 дней.
К статье приложена информационная база, в которой реализован описанный функционал, примеры отчетов, а также процедура заполнения и пересчета регистра.
Подсчитываем дни с помощью регистра сведений РегламентированныйПроизводственныйКалендарь.
* Стоит условие что дата окончания должна попадать на рабочий день.
* Начальная дата не проверяется на то, что должна быть рабочим днем.
* Начальная дата за рабочий день не считается.
* Нет проверок что календарь не заполнен, это можно сделать отдельно.
ВЫБРАТЬ
Даты.ДатаНачала КАК ДатаНачала,
Даты.ДатаОкончания КАК ДатаОкончания,
КОЛИЧЕСТВО(РПК.ДатаКалендаря) - 1 КАК КоличествоРабочихДней
ИЗ
(ВЫБРАТЬ
ПодсчетРабочихДней.ДатаНачала КАК ДатаНачала,
ПодсчетРабочихДней.ДатаОкончания КАК ДатаОкончания
ИЗ
(ВЫБРАТЬ
Календарь1.ДатаКалендаря КАК ДатаНачала,
Календарь2.ДатаКалендаря КАК ДатаОкончания
ИЗ
РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК Календарь1,
(ВЫБРАТЬ
Календарь2.ДатаКалендаря КАК ДатаКалендаря
ИЗ
РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК Календарь2
ГДЕ
(Календарь2.ДатаКалендаря > &Дата1
И Календарь2.ДатаКалендаря < &Дата2)
И Календарь2.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий)) КАК Календарь2
ГДЕ
Календарь1.ДатаКалендаря >= &Дата1
И Календарь1.ДатаКалендаря <= &Дата2
И Календарь1.ДатаКалендаря < Календарь2.ДатаКалендаря) КАК ПодсчетРабочихДней) КАК Даты,
РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РПК
ГДЕ
РПК.ДатаКалендаря МЕЖДУ Даты.ДатаНачала И Даты.ДатаОкончания
И РПК.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий)
СГРУППИРОВАТЬ ПО
Даты.ДатаНачала,
Даты.ДатаОкончания
УПОРЯДОЧИТЬ ПО
ДатаНачала,
ДатаОкончания
(3) Дело в том что есть еще другой запрос в котором соответственно есть дата начальная и число рабочих дней и нужно получить дату окончания.
Этот запрос не поможет, так как даты это параметры. А мой можно прицепить к другому запросу и получить дату окончания исходя из даты начала и количества рабочих дней.
(2) Нет, просто искал готовое решение и не нашел, выложил может кому пригодится.
В моем случае есть бизнес процесс который начинается с определенной даты, а закончится должен через сколько то рабочих дней и какой датой он должен окончится нужно вычислить.
Читайте также: