Как реализовать выбор периода по неделям в 1С:ERP на управляемых формах?

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием
← На главную

В стандартном функционале 1С:Предприятие 8.3, включая такие сложные системы, как 1С:ERP или 1С:Комплексная автоматизация, механизм выбора стандартного периода отлично справляется с днями, месяцами и кварталами. Однако задача предоставить пользователю возможность выбрать конкретную неделю года (например, «15-я неделя 2024 года») часто ставит разработчиков в тупик, так как готового виджета для этого в платформе не предусмотрено. В этой статье мы подробно разберем, как реализовать такой функционал самостоятельно, учитывая требования законодательства и удобство интерфейса.

Анализ задачи и стандартов определения недель

Прежде чем приступать к разработке формы, нам необходимо определиться с тем, что именно мы считаем «первой неделей года». В мировой практике и в 1С существует несколько подходов. Если мы обратимся к функции НеделяГода(), то увидим, что она принимает второй параметр — СпособОпределенияНомераНедели. Рассмотрим это подробнее:

  1. Локально: Зависит от региональных настроек операционной системы.
  2. По четвергам (ISO 8601): Это международный стандарт, принятый также и в РФ. Согласно ему, первой неделей года считается та, на которую выпадает первый четверг года. Именно этот вариант чаще всего требуется в производственных отчетах ERP.

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

Вариант 1: Создание вспомогательной формы выбора

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

На форме рекомендуется разместить поле выбора года и список доступных недель. Чтобы пользователь не гадал, какие даты входят в «20-ю неделю», представление в списке должно быть максимально информативным.

Рассмотрим пример кода для заполнения списка недель на форме:


&НаСервере
Процедура ЗаполнитьСписокНедель(ВыбранныйГод)
    СписокНедель.Очистить();
    
    // Начинаем с 1 января выбранного года
    ТекущаяДата = НачалоГода(Дата(ВыбранныйГод, 1, 1));
    КонецГода = КонецГода(ТекущаяДата);
    
    // Цикл по всем неделям года
    Пока ТекущаяДата <= КонецГода Цикл
        НомерНедели = НеделяГода(ТекущаяДата, СпособОпределенияНомераНедели.ПоЧетвергам);
        НачалоНедели = НачалоНедели(ТекущаяДата);
        КонецНедели = КонецНедели(ТекущаяДата);
        
        Представление = "Неделя №" + НомерНедели + " (" + Формат(НачалоНедели, "ДФ=dd.MM.yyyy") + " - " + Формат(КонецНедели, "ДФ=dd.MM.yyyy") + ")";
        
        // Добавляем в список значений, где значением будет начало недели
        СписокНедель.Добавить(НачалоНедели, Представление);
        
        // Переходим к следующему понедельнику
        ТекущаяДата = НачалоНедели + 7 * 24 * 60 * 60;
    КонецЦикла;
КонецПроцедуры

Этот подход позволяет пользователю видеть четкие границы периода, что исключает ошибки ввода. Выбранное значение (начало недели) затем легко передать в параметры запроса или в СтандартныйПериод.

Вариант 2: Использование алгоритма вычисления границ по номеру

Иногда требуется реализовать ввод номера недели напрямую в поле (например, для массового ввода данных). В этом случае нам нужно уметь программно вычислять даты «с... по...», зная только год и номер недели. Выясним причину сложности: 1 января не всегда является понедельником, поэтому простое прибавление (Номер * 7) дней даст неточный результат.

Правильный алгоритм расчета границ недели выглядит следующим образом:


Функция ПолучитьГраницыНедели(Год, НомерНедели) Экспорт
    // Находим дату начала года
    ДатаНачалаГода = Дата(Год, 1, 1);
    
    // Находим первый четверг года (по ISO 8601 первая неделя та, где первый четверг)
    ТекущаяДата = ДатаНачалаГода;
    Пока ДеньНедели(ТекущаяДата) <> 4 Цикл
        ТекущаяДата = ТекущаяДата + 86400;
    КонецЦикла;
    
    // Теперь ТекущаяДата — это четверг 1-й недели. 
    // Прибавляем нужное количество недель
    НужныйЧетверг = ТекущаяДата + (НомерНедели - 1) * 7 * 86400;
    
    Результат = Новый Структура;
    Результат.Вставить("ДатаНачала", НачалоНедели(НужныйЧетверг));
    Результат.Вставить("ДатаОкончания", КонецНедели(НужныйЧетверг));
    
    Возврат Результат;
КонецФункции

Обратите внимание на проблему 53-й недели. В некоторых годах (например, 2020 или 2026) календарь содержит 53 недели. При программном формировании выбора нельзя жестко ограничивать цикл 52-мя неделями, иначе данные за последние дни года могут не попасть в отчет.

Вариант 3: Интеграция с СКД и стандартными периодами

Если ваша задача — сделать выбор недели в отчете на базе Системы компоновки данных (СКД), можно воспользоваться механизмом расширения параметров. Хотя штатный тип СтандартныйПериод не предлагает выбор недели по номеру, мы можем добавить на форму отчета два реквизита: ВыбранныйГод и НомерНедели.

При изменении любого из этих реквизитов мы будем программно устанавливать границы основного параметра периода отчета. Рассмотрим пример обработки события на форме отчета:


&НаКлиенте
Процедура НомерНеделиПриИзменении(Элемент)
    Границы = ПолучитьГраницыНеделиНаСервере(Объект.Год, Объект.НомерНедели);
    
    // Устанавливаем период в параметрах СКД
    ЗначениеПараметра = Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("Период"));
    Если ЗначениеПараметра <> Неопределено Тогда
        ЗначениеПараметра.Значение.Вариант = ВариантСтандартногоПериода.ПроизвольныйПериод;
        ЗначениеПараметра.Значение.ДатаНачала = Границы.ДатаНачала;
        ЗначениеПараметра.Значение.ДатаОкончания = Границы.ДатаОкончания;
        ЗначениеПараметра.Использование = Истина;
    КонецЕсли;
КонецПроцедуры

Рекомендации по юзабилити (на примере ЗУП 3.1)

Разберем опыт конфигурации Зарплата и Управление Персоналом. Там выбор месяца реализован через удобную графическую форму. Для выбора недели можно использовать аналогичный подход с использованием ПоляТабличногоДокумента. Мы можем вывести календарную сетку на год, где каждая строка — это неделя. При клике на любую ячейку в строке мы выделяем всю неделю и возвращаем её границы в основную форму.

Важные моменты для реализации в ERP:

Таким образом, создание собственного механизма выбора недели в 1С:ERP не является сложной задачей, если четко следовать стандартам ISO 8601 и предоставлять пользователю визуальное подтверждение выбранных дат.

← На главную