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