Как правильно использовать ЗаполнитьЗначенияСвойств: почему в одних случаях мы указываем объект, а в других — метод Добавить?

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

Метод ЗаполнитьЗначенияСвойств является одним из самых часто используемых инструментов в арсенале разработчика 1С. Он позволяет быстро копировать данные между объектами, сопоставляя их по именам свойств. Однако у начинающих разработчиков часто возникает вопрос: почему при работе со структурой мы передаем саму переменную-приемник, а при работе с таблицей значений — результат вызова метода Добавить()? В этой статье мы подробно разберем механику работы этого метода, проанализируем различные сценарии и выясним технические нюансы, которые помогут вам писать более эффективный код.

Разбор механики: Структура vs Строка таблицы значений

Для начала проанализируем ситуацию, описанную в вопросе. Рассмотрим два примера кода и разберемся, что происходит "под капотом" платформы.

Пример 1: Работа со структурой


Источник = Новый Структура("Наименование, Код", "Дерево", 1);
Получатель = Новый Структура("Наименование, Код");
ЗаполнитьЗначенияСвойств(Получатель, Источник);

В данном случае переменная Получатель сама по себе является объектом, у которого есть свойства "Наименование" и "Код". Метод ЗаполнитьЗначенияСвойств напрямую обращается к этим свойствам и записывает в них данные из источника. Здесь все логично: объект уже существует, и его поля готовы к заполнению.

Пример 2: Работа с таблицей значений


Источник = Новый Структура("Наименование, Код", "Дерево", 1);
Получатель = Новый ТаблицаЗначений;
Получатель.Колонки.Добавить("Наименование");
Получатель.Колонки.Добавить("Код");

// Правильный способ:
ЗаполнитьЗначенияСвойств(Получатель.Добавить(), Источник);

Разберем, почему здесь нельзя просто написать ЗаполнитьЗначенияСвойств(Получатель, Источник). Сама ТаблицаЗначений как объект не обладает свойствами "Наименование" или "Код". Эти свойства (колонки) принадлежат её строкам. Если мы передадим саму таблицу в качестве приемника, платформа не найдет совпадений по именам свойств и ничего не скопирует (либо возникнет логическая ошибка, так как у таблицы нет таких полей данных).

Когда мы пишем Получатель.Добавить(), происходит следующее:

  1. Сначала выполняется метод Добавить() объекта ТаблицаЗначений.
  2. Этот метод создает новую пустую строку и возвращает её как объект типа СтрокаТаблицыЗначений.
  3. Этот возвращенный объект (конкретная строка) передается в качестве первого параметра (приемника) в функцию ЗаполнитьЗначенияСвойств.
  4. Метод видит, что у строки есть колонки "Наименование" и "Код", находит их в источнике и заполняет данными.

Таким образом, важно запомнить: ЗаполнитьЗначенияСвойств — это не про формирование коллекции, а про заполнение конкретного элемента этой коллекции.

Синтаксис и параметры метода

Давайте освежим в памяти синтаксис функции, чтобы понимать все её возможности:

ЗаполнитьЗначенияСвойств(<Приемник>, <Источник>, <СписокСвойств>, <ИсключаяСвойства>)

Производительность: когда лучше использовать ручное присвоение?

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

Малое количество свойств: Если вам нужно перенести всего 1–3 поля, прямое присвоение (Приемник.Имя = Источник.Имя) будет работать быстрее. В высоконагруженных циклах (например, обработка сотен тысяч строк) разница может стать заметной.

Большие коллекции: Если свойств много (более 5–10) или состав полей может меняться со временем, ЗаполнитьЗначенияСвойств предпочтительнее. Это делает ваш код чище, короче и устойчивее к изменениям в структуре метаданных. Вам не придется дописывать новые строки кода при добавлении нового реквизита в документ — метод подхватит его автоматически.

Нюансы типизации и "поверхностное" копирование

Рассмотрим важные технические особенности, о которых часто забывают:

1. Ссылочные типы. Метод выполняет поверхностное копирование. Если реквизит является ссылкой (например, СправочникСсылка.Контрагенты), в приемник запишется именно эта ссылка. Новый объект-дубликат в базе создан не будет.

2. Приведение типов. Если типы свойств не совпадают, платформа попытается их привести. Например, если в источнике число 10, а в приемнике (в колонке таблицы значений) жестко задан тип Строка, значение может быть преобразовано. Однако, если автоматическое приведение невозможно, в приемник может записаться значение по умолчанию (например, 0 для чисел) или возникнет ошибка, если объект-приемник накладывает строгие ограничения на запись.

3. Свойства только для чтения. Метод игнорирует свойства, которые недоступны для записи. Вы не сможете изменить свойство Ссылка у существующего документа с помощью этого метода — платформа просто пропустит это поле без выдачи ошибки.

4. Неопределено и Null. Если в источнике свойство имеет значение Неопределено, оно будет честно скопировано в приемник, затирая те данные, которые там были до этого. Будьте осторожны, если ваша цель — "дозаполнить" только пустые поля.

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

Часто при копировании данных из одного документа в другой разработчики забывают про четвертый параметр. Рассмотрим пример:


// Копируем данные из одного заказа в другой, но не хотим менять дату и номер
ЗаполнитьЗначенияСвойств(НовыйЗаказ, СтарыйЗаказ, , "Номер, Дата, Ссылка");

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

Подводя итог, можно сказать, что ЗаполнитьЗначенияСвойств — это мощный инструмент рефлексии в 1С. Главное — четко понимать, какой именно объект вы передаете в качестве приемника: всю коллекцию или её конкретный элемент.

← На главную