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