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