Как динамически обратиться к колонкам дней (Часов1...Часов31) в запросе и СКД 1С

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

При работе с документами ввода индивидуальных графиков в 1С:Зарплата и Управление Персоналом часто возникает необходимость получить отработаные часы за конкретный день месяца. В табличной части документа реквизиты хранятся в отдельных колонках с именами Часов1, Часов2, ..., Часов31. Рассмотрим, как правильно выгрузить значение нужной ячейки, если номер дня передается через параметр.

Ограничения языка запросов 1С

Разберем типичную ошибку. Начинающие разработчики пытаются сложить имя реквизита с параметром прямо в запросе, например: ВводИндивидуальныхГрафиковРаботыОрганизацииГрафикРаботы.Часов1 + &ПараметрНомерДня или конкатенировать строку с параметром.

В языке запросов платформы 1С нельзя динамически формировать имена полей с помощью параметров или выражений. Имена реквизитов и колонок в тексте запроса должны быть прописаны явно. Однако существует несколько способов решения этой задачи в зависимости от того, где используется запрос — в BSL-коде или в Системе компоновки данных (СКД).

Способ 1. Использование конструкции ВЫБОР КОГДА в тексте запроса

Если требуется оставить текст запроса статичным без написания кода BSL, проанализируем номер дня с помощью условных операторов ВЫБОР КОГДА. Это универсальный подход, который отлично работает как в обычных запросах, так и в схемах компоновки данных.

Посмотрим на пример оформления условия в тексте запроса:


ВЫБРАТЬ
    ГрафикРаботы.Ссылка КАК Ссылка,
    ГрафикРаботы.Сотрудник КАК Сотрудник,
    ВЫБОР 
        КОГДА &ПараметрНомерДня = 1 ТОГДА ГрафикРаботы.Часов1
        КОГДА &ПараметрНомерДня = 2 ТОГДА ГрафикРаботы.Часов2
        КОГДА &ПараметрНомерДня = 3 ТОГДА ГрафикРаботы.Часов3
        // ... аналогично для всех дней до 31
        КОГДА &ПараметрНомерДня = 31 ТОГДА ГрафикРаботы.Часов31
        ИНАЧЕ 0
    КОНЕЦ КАК НужныйДень
ИЗ
    Документ.ВводИндивидуальныхГрафиковРаботыОрганизации.ГрафикРаботы КАК ГрафикРаботы
ГДЕ
    ГрафикРаботы.Ссылка.ПериодРегистрации = &ПериодРегистрации
    И ГрафикРаботы.Сотрудник = &Сотрудник

Способ 2. Динамическая подстановка имени поля в BSL-коде

Если запрос формируется программно во внешнем модуле или обработке, удобнее всего сформировать имя поля до передачи текста в объект Запрос. Для этого заменим шаблонную метку в тексте запроса на реальное имя реквизита.

Рассмотрим по шагам выполнение данного алгоритма:

  1. Создаем текст запроса со специальной подстановкой, например {ИмяПоляДня}.
  2. Формируем имя поля путем сложения префикса и номера дня.
  3. Заменяем текстовую метку в запросе помощью функции СтрЗаменить.

ИмяПоля = "Часов" + Формат(ПараметрНомерДня, "ЧГ=0");

ТекстЗапроса = "
|ВЫБРАТЬ
|   ГрафикРаботы.Сотрудник,
|   ГрафикРаботы." + ИмяПоля + " КАК НужныйДень
|ИЗ
|   Документ.ВводИндивидуальныхГрафиковРаботыОрганизации.ГрафикРаботы КАК ГрафикРаботы
|ГДЕ
|   ГрафикРаботы.Сотрудник = &Сотрудник";

Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("Сотрудник", ВыбранныйСотрудник);
Результат = Запрос.Выполнить();

Способ 3. Программная смена текста запроса в СКД

Если отчёт разрабатывается на СКД и требуется динамическая подстановка имени колонки, модифицируем текст запроса программно перед компоновкой макета. Для этого используется объект НаборДанныхЗапросСхемыКомпоновкиДанных и его свойство Запрос.

Проанализируем пример кода в модуле объекта отчета СКД при формировании отчета:


ИмяПоля = "Часов" + Формат(НомерДня, "ЧГ=0");

// Получаем схему компоновки данных
Схема = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");

// Находим набор данных типа "Запрос"
НаборДанных = Схема.НаборыДанных.Найти("НаборДанных1");
Если НаборДанных <> Неопределено Тогда
    НаборДанных.Запрос = СтрЗаменить(НаборДанных.Запрос, "&ИмяПоляДня", ИмяПоля);
КонецЕсли;

Способ 4. Обращение к периодическим регистрам сведений

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

Обращение к регистру исключает работу с динамическими колонками Часов1...Часов31, так как данные хранятся по дням в отдельном разрезе измерений и ресурсов. В этом случае отбор по точной дате выполняется с помощью функции ДОБАВИТЬКДАТЕ:


ВЫБРАТЬ
    Графики.Сотрудник,
    Графики.Часов
ИЗ
    РегистрСведений.ГрафикиРаботыСотрудников КАК Графики
ГДЕ
    Графики.Период = ДОБАВИТЬКДАТЕ(&НачалоМесяца, ДЕНЬ, &ПараметрНомерДня - 1)
    И Графики.Сотрудник = &Сотрудник

Каждый из рассмотренных способов имеет свои преимущества: ВЫБОР КОГДА подходит для простых статических отчетов СКД без написания кода, динамическое формирование текста в BSL — для гибкой разработки в модулях, а обращение к регистрам сведений является наиболее правильным архитектурным решением в тиражных конфигурациях 1С.

← На главную