Почему табличная часть заполняется пустыми строками при программном заполнении в 1С

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

При разработке в среде 1С:Предприятие часто возникает задача программного заполнения табличных частей документа или справочника данными из запроса. Типичная ситуация: код выполняется без ошибок, строки в таблице создаются, но данные в них не отображаются — колонки остаются пустыми. Давайте разберем по шагам, почему это происходит, как работает механизм сопоставления свойств и какие методы заполнения данных считаются наиболее эффективными.

Разбор механизма работы ЗаполнитьЗначенияСвойств

Рассмотрим ситуацию, с которой столкнулся автор темы. Проблема заключается в использовании метода ЗаполнитьЗначенияСвойств. Этот метод является мощным инструментом платформы, предназначенным для копирования значений из одного объекта в другой, если у них совпадают имена свойств (реквизитов). Проанализируем, как он работает «под капотом».

Когда мы вызываем ЗаполнитьЗначенияСвойств(Получатель, Источник), платформа выполняет перебор всех доступных реквизитов объекта-получателя. Для каждого найденного имени она ищет реквизит с точно таким же именем в объекте-источнике. Если имена совпадают (регистр при этом не учитывается), значение копируется.

В коде автора запросом выбиралось поле Дети.Ссылка. По умолчанию в результате запроса это поле так и называется — Ссылка. Однако в табличной части (ТЧ) реквизит, скорее всего, назывался Ребенок. Поскольку имя Ссылка не равно имени Ребенок, метод просто пропускал это поле, не находя соответствия, и строка оставалась пустой.

Решение проблемы через псевдонимы в запросе

Самый простой способ исправить ситуацию при использовании ЗаполнитьЗначенияСвойств — это привести имена полей запроса в соответствие с именами реквизитов табличной части. Для этого мы используем конструкцию КАК в тексте запроса. Разберем исправленный пример кода:


&НаСервере
Процедура ЗаполнитьДетей()
    // Устанавливаем псевдоним поля Ссылка, чтобы он совпадал с именем реквизита ТЧ "Ребенок"
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Дети.Ссылка КАК Ребенок
        |ИЗ
        |   Справочник.Дети КАК Дети";
    
    РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();
    
    Пока Выборка.Следующий() Цикл
        // Добавляем новую строку в табличную часть
        НовСтр = Объект.Посещаемость.Добавить();
        // Теперь имена "Ребенок" в выборке и в ТЧ совпадают
        ЗаполнитьЗначенияСвойств(НовСтр, Выборка); 
    КонецЦикла;
КонецПроцедуры

Этот подход удобен тем, что если в вашей табличной части много колонок (например, Ребенок, Возраст, Группа), и вы назовете поля в запросе точно так же, одна строка ЗаполнитьЗначенияСвойств заполнит сразу все данные.

Явное присвоение значений как альтернатива

Проанализируем другой подход. Если вам нужно заполнить всего одно или два поля, использование универсального метода ЗаполнитьЗначенияСвойств может быть избыточным. Платформа тратит дополнительные ресурсы на анализ метаданных и поиск совпадений имен. В таких случаях гораздо эффективнее использовать прямое обращение к реквизитам.

Посмотрим на пример явного присвоения:


Пока Выборка.Следующий() Цикл
    НовСтр = Объект.Посещаемость.Добавить();
    // Явно указываем, какое поле откуда заполняется
    НовСтр.Ребенок = Выборка.Ребенок;
КонецЦикла;

Преимущества этого способа:

  1. Скорость выполнения: Прямое присвоение работает быстрее, чем универсальный перебор свойств.
  2. Простота отладки: Вы сразу видите, какие данные передаются, и типизация проверяется на этапе написания кода.
  3. Независимость от имен: Поле в запросе может называться как угодно, вам не обязательно подгонять его под имя в ТЧ.

Использование метода Загрузить() для оптимизации производительности

Если в вашей табличной части предполагается большое количество строк (сотни или тысячи), использование метода Добавить() внутри цикла может привести к замедлению работы интерфейса. Платформа вынуждена пересчитывать индексы и обновлять коллекцию на каждой итерации.

Выясним причину, почему метод Загрузить() считается более профессиональным. Он позволяет заменить все строки табличной части данными из таблицы значений одним блоком. Рассмотрим, как реализовать этот алгоритм:


&НаСервере
Процедура ЗаполнитьДетейОптимизировано()
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Дети.Ссылка КАК Ребенок
        |ИЗ
        |   Справочник.Дети КАК Дети";
    
    // Выгружаем результат запроса сразу в таблицу значений
    ТаблицаРезультата = Запрос.Выполнить().Выгрузить();
    
    // Загружаем таблицу в табличную часть объекта
    // ВАЖНО: имена колонок в ТаблицаРезультата должны СОВПАДАТЬ с именами реквизитов ТЧ
    Объект.Посещаемость.Загрузить(ТаблицаРезультата);
КонецПроцедуры

Метод Загрузить полностью очищает существующие строки и записывает новые. Это происходит значительно быстрее, так как операция выполняется на уровне платформенных оптимизаций работы с памятью.

Важные рекомендации по именованию и типам данных

В процессе обсуждения на форуме была замечена ошибка в слове «Посещаймость». Проанализируем ситуацию: в 1С крайне важно соблюдать точность в написании имен объектов метаданных. Если в конфигураторе вы создали реквизит Посещаемость, а в коде обращаетесь к Посещаймость, система выдаст ошибку «Поле объекта не обнаружено». Опечатки в коде — это не только вопрос эстетики, но и причина трудноуловимых багов.

Основные правила безопасного заполнения:

Подводя итог, можно сказать, что «пустые строки» — это всегда следствие несовпадения имен или типов. Используя псевдонимы в запросах или метод Загрузить(), вы сделаете свой код более надежным и производительным.

← На главную