При работе с документами ввода индивидуальных графиков в 1С:Зарплата и Управление Персоналом часто возникает необходимость получить отработаные часы за конкретный день месяца. В табличной части документа реквизиты хранятся в отдельных колонках с именами Часов1, Часов2, ..., Часов31. Рассмотрим, как правильно выгрузить значение нужной ячейки, если номер дня передается через параметр.
Разберем типичную ошибку. Начинающие разработчики пытаются сложить имя реквизита с параметром прямо в запросе, например: ВводИндивидуальныхГрафиковРаботыОрганизацииГрафикРаботы.Часов1 + &ПараметрНомерДня или конкатенировать строку с параметром.
В языке запросов платформы 1С нельзя динамически формировать имена полей с помощью параметров или выражений. Имена реквизитов и колонок в тексте запроса должны быть прописаны явно. Однако существует несколько способов решения этой задачи в зависимости от того, где используется запрос — в BSL-коде или в Системе компоновки данных (СКД).
Если требуется оставить текст запроса статичным без написания кода BSL, проанализируем номер дня с помощью условных операторов ВЫБОР КОГДА. Это универсальный подход, который отлично работает как в обычных запросах, так и в схемах компоновки данных.
Посмотрим на пример оформления условия в тексте запроса:
ВЫБРАТЬ
ГрафикРаботы.Ссылка КАК Ссылка,
ГрафикРаботы.Сотрудник КАК Сотрудник,
ВЫБОР
КОГДА &ПараметрНомерДня = 1 ТОГДА ГрафикРаботы.Часов1
КОГДА &ПараметрНомерДня = 2 ТОГДА ГрафикРаботы.Часов2
КОГДА &ПараметрНомерДня = 3 ТОГДА ГрафикРаботы.Часов3
// ... аналогично для всех дней до 31
КОГДА &ПараметрНомерДня = 31 ТОГДА ГрафикРаботы.Часов31
ИНАЧЕ 0
КОНЕЦ КАК НужныйДень
ИЗ
Документ.ВводИндивидуальныхГрафиковРаботыОрганизации.ГрафикРаботы КАК ГрафикРаботы
ГДЕ
ГрафикРаботы.Ссылка.ПериодРегистрации = &ПериодРегистрации
И ГрафикРаботы.Сотрудник = &Сотрудник
Если запрос формируется программно во внешнем модуле или обработке, удобнее всего сформировать имя поля до передачи текста в объект Запрос. Для этого заменим шаблонную метку в тексте запроса на реальное имя реквизита.
Рассмотрим по шагам выполнение данного алгоритма:
{ИмяПоляДня}.СтрЗаменить.
ИмяПоля = "Часов" + Формат(ПараметрНомерДня, "ЧГ=0");
ТекстЗапроса = "
|ВЫБРАТЬ
| ГрафикРаботы.Сотрудник,
| ГрафикРаботы." + ИмяПоля + " КАК НужныйДень
|ИЗ
| Документ.ВводИндивидуальныхГрафиковРаботыОрганизации.ГрафикРаботы КАК ГрафикРаботы
|ГДЕ
| ГрафикРаботы.Сотрудник = &Сотрудник";
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("Сотрудник", ВыбранныйСотрудник);
Результат = Запрос.Выполнить();
Если отчёт разрабатывается на СКД и требуется динамическая подстановка имени колонки, модифицируем текст запроса программно перед компоновкой макета. Для этого используется объект НаборДанныхЗапросСхемыКомпоновкиДанных и его свойство Запрос.
Проанализируем пример кода в модуле объекта отчета СКД при формировании отчета:
ИмяПоля = "Часов" + Формат(НомерДня, "ЧГ=0");
// Получаем схему компоновки данных
Схема = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
// Находим набор данных типа "Запрос"
НаборДанных = Схема.НаборыДанных.Найти("НаборДанных1");
Если НаборДанных <> Неопределено Тогда
НаборДанных.Запрос = СтрЗаменить(НаборДанных.Запрос, "&ИмяПоляДня", ИмяПоля);
КонецЕсли;
Выясним альтернативный вариант получения данных. В конфигурациях ЗУП при проведении документов графика данные записываются в специализированные периодические регистры сведений (например, регистр сведений графиков работы сотрудников).
Обращение к регистру исключает работу с динамическими колонками Часов1...Часов31, так как данные хранятся по дням в отдельном разрезе измерений и ресурсов. В этом случае отбор по точной дате выполняется с помощью функции ДОБАВИТЬКДАТЕ:
ВЫБРАТЬ
Графики.Сотрудник,
Графики.Часов
ИЗ
РегистрСведений.ГрафикиРаботыСотрудников КАК Графики
ГДЕ
Графики.Период = ДОБАВИТЬКДАТЕ(&НачалоМесяца, ДЕНЬ, &ПараметрНомерДня - 1)
И Графики.Сотрудник = &Сотрудник
Каждый из рассмотренных способов имеет свои преимущества: ВЫБОР КОГДА подходит для простых статических отчетов СКД без написания кода, динамическое формирование текста в BSL — для гибкой разработки в модулях, а обращение к регистрам сведений является наиболее правильным архитектурным решением в тиражных конфигурациях 1С.