К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как одну структуру скопировать в другую в 1С

Как одну структуру скопировать в другую в 1С: ЗаполнитьЗначенияСвойств, перебор элементов, сериализация. Примеры кода, ограничения и типичные ошибки.

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

Встроенного метода «Скопировать()» у структуры нет, поэтому копирование выполняют другими средствами: стандартной процедурой ЗаполнитьЗначенияСвойств, ручным перебором элементов, сериализацией через JSON или XDTO. Каждый способ имеет свои ограничения — от поверхностного копирования ссылок на вложенные объекты до потери типов при сериализации.

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

Что такое структура в 1С и как она хранится

Структура создаётся конструктором Новый Структура("Имя,Организация,Сумма") или Новый Структура с последующим добавлением ключей через Вставить(). Ключи — строки, соответствующие правилам именования переменных: без пробелов, начиная с буквы. Значениями могут быть любые типы: числа, строки, даты, ссылки, другие структуры, массивы, таблицы значений.

Структура передаётся по ссылке. Если присвоить одну переменную другой (Структура2 = Структура1), обе переменные будут указывать на один и тот же объект в памяти. Любое изменение через одну переменную отразится в другой — это не копирование, а создание второго указателя. Именно поэтому для реального копирования нужны отдельные приёмы.

Копирование через ЗаполнитьЗначенияСвойств

Стандартная процедура ЗаполнитьЗначенияСвойств(Приемник, Источник) — самый короткий способ перенести данные. Она копирует значения свойств, которые существуют в обоих объектах. Если приёмник — структура, в неё попадут только те ключи источника, которые уже объявлены в приёмнике.

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

Источник = Новый Структура("Имя,Возраст,Город", "Иван", 30, "Москва");

Приемник = Новый Структура("Имя,Возраст,Город,Телефон");

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

// Приемник.Имя = "Иван", Приемник.Телефон = Неопределено

Третий необязательный параметр — список свойств через запятую, если нужно скопировать только часть ключей: ЗаполнитьЗначенияСвойств(Приемник, Источник, "Имя,Возраст"). Четвёртый параметр — список исключаемых свойств. Это удобно, когда нужно перенести всё, кроме служебных полей.

Ограничение способа: приёмник должен заранее содержать все нужные ключи. Если структура-приёмник пустая, ЗаполнитьЗначенияСвойств не создаст в ней новые ключи — она останется пустой. Для копирования в пустую структуру используйте перебор.

Копирование перебором элементов

Цикл Для Каждого по структуре — универсальный способ, который работает с любым приёмником, включая пустой. Каждый элемент структуры представлен объектом КлючИЗначение, у которого есть свойства Ключ и Значение.

Функция СкопироватьСтруктуру(Источник)

Результат = Новый Структура;

Для Каждого Элемент Из Источник Цикл

Результат.Вставить(Элемент.Ключ, Элемент.Значение);

КонецЦикла;

Возврат Результат;

КонецФункции

Такой подход позволяет добавить логику: пропускать пустые значения, преобразовывать типы, переименовывать ключи, фильтровать по префиксу. Например, чтобы скопировать только заполненные значения:

Для Каждого Элемент Из Источник Цикл

Если ЗначениеЗаполнено(Элемент.Значение) Тогда

Результат.Вставить(Элемент.Ключ, Элемент.Значение);

КонецЕсли;

КонецЦикла;

Перебор также подходит для копирования структуры в соответствие и обратно — достаточно заменить тип приёмника. Учтите, что это по-прежнему поверхностная копия: вложенные объекты передаются по ссылке.

Глубокое копирование вложенных объектов

Когда структура содержит другие структуры, массивы или таблицы значений, поверхностного копирования недостаточно. Самый практичный способ глубокого копирования — сериализация через JSON: объект преобразуется в строку, затем обратно в новый объект. Все вложенные уровни при этом создаются заново.

Функция ГлубокаяКопия(Источник)

Запись = Новый ЗаписьJSON;

Запись.УстановитьСтроку();

ЗаписатьJSON(Запись, Источник);

СтрокаJSON = Запись.Закрыть();

Чтение = Новый ЧтениеJSON;

Чтение.УстановитьСтроку(СтрокаJSON);

Возврат ПрочитатьJSON(Чтение); // по умолчанию возвращает Соответствие

КонецФункции

Нюансы способа: ПрочитатьJSON по умолчанию возвращает соответствие, а не структуру — для получения структуры передайте вторым параметром Ложь или обработайте результат. Даты сериализуются в строки, ссылки и таблицы значений через JSON не переносятся корректно. Для сложных типов используют сериализацию XDTO (СериализаторXDTO.ЗаписатьXML / ПрочитатьXML), которая сохраняет типы платформы.

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

Сравнение способов копирования

ЗаполнитьЗначенияСвойств

Быстро и коротко. Ограничение: приёмник должен заранее содержать ключи; только поверхностная копия.

Перебор Для Каждого

Работает с пустым приёмником, позволяет фильтровать и преобразовывать. Ограничение: поверхностная копия, чуть больше кода.

Сериализация JSON/XDTO

Даёт настоящую глубокую копию. Ограничение: JSON теряет типы (даты, ссылки), XDTO требует больше кода и медленнее.

Рекурсивная функция

Полный контроль над копированием любых вложенностей. Ограничение: нужно вручную обрабатывать все типы коллекций.

Копирование структуры в объект конфигурации

Частая практическая задача — перенести данные из структуры в объект справочника или документа. Здесь ЗаполнитьЗначенияСвойств работает особенно удобно: она сопоставляет ключи структуры с реквизитами объекта по именам.

Данные = Новый Структура("Наименование,ИНН,КПП", "ООО Ромашка", "7700000000", "770001001");

НовыйКонтрагент = Справочники.Контрагенты.СоздатьЭлемент();

ЗаполнитьЗначенияСвойств(НовыйКонтрагент, Данные);

НовыйКонтрагент.Записать();

Ключи, которых нет среди реквизитов объекта, игнорируются — ошибки не возникает. Это позволяет использовать одну структуру-источник для заполнения разных объектов. Обратная операция — выгрузка реквизитов объекта в структуру — делается через перебор метаданных объекта или через ЗаполнитьЗначенияСвойств(Структура, Объект) с заранее подготовленным набором ключей.

Проверка результата и типичные ошибки

После копирования убедитесь, что получен независимый объект: измените значение в копии и проверьте, что оригинал не изменился. Для вложенных структур проверьте отдельно — именно на вложенном уровне чаще всего обнаруживается, что копия была поверхностной.

Сравнить две структуры на равенство оператором = нельзя — для объектов он сравнивает ссылки, а не содержимое. Для сравнения содержимого перебирайте ключи и сравнивайте значения поэлементно или сериализуйте обе структуры в JSON и сравните строки.

Типичные ошибки
01
Присваивание Структура2 = Структура1 вместо копирования — обе переменные указывают на один объект, изменения отражаются в обеих.
02
Ожидание глубокой копии от ЗаполнитьЗначенияСвойств — вложенные структуры и массивы остаются общими, правка копии портит оригинал.
03
Вызов ЗаполнитьЗначенияСвойств с пустым приёмником — ключи не создаются, результат пустой.
04
Попытка сравнить структуры оператором «=» — сравниваются ссылки, а не содержимое, результат почти всегда Ложь.
05
Сериализация ссылок и таблиц значений через JSON — типы теряются, данные восстанавливаются некорректно.

Выбор способа под задачу

Для простых плоских структур с известным набором ключей достаточно ЗаполнитьЗначенияСвойств — это самый читаемый вариант. Если приёмник пустой или нужна фильтрация значений, используйте перебор. Для независимой копии сложной вложенной структуры — сериализацию или рекурсию.

Маршрут решения

Как выбрать способ

Приёмник уже содержит нужные ключи, вложенных объектов нетИспользуйте ЗаполнитьЗначенияСвойств — минимум кода
Приёмник пустой или нужно фильтровать значенияПеребирайте элементы циклом Для Каждого с Вставить()
В структуре есть вложенные структуры или массивы и нужна полная независимостьПрименяйте сериализацию через XDTO или рекурсивное копирование
Копируете данные в объект справочника или документаЗаполните реквизиты через ЗаполнитьЗначенияСвойств(Объект, Структура)
Внутри структуры есть таблица значенийСкопируйте её отдельно методом ТЗ.Скопировать()

В прикладных решениях часто встречается готовая функция общего модуля — в типовых конфигурациях это ОбщегоНазначения.СкопироватьРекурсивно() или аналогичные методы. Перед написанием собственного велосипеда проверьте, нет ли подходящей функции в стандартных подсистемах вашей конфигурации.

Итог

Что важно запомнить

Простое присваивание не копирует структуру, а создаёт вторую ссылку. Для плоских структур используйте ЗаполнитьЗначенияСвойств или перебор, для вложенных — сериализацию или рекурсию. После копирования проверяйте независимость копии изменением тестового значения.

Частые вопросы

Можно ли скопировать структуру одной строкой?

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

Почему после копирования изменения в копии видны и в оригинале?

Либо вы присвоили структуру через «=» (получили вторую ссылку на тот же объект), либо выполнили поверхностное копирование, а изменяете вложенную структуру или массив. Вложенные объекты копируются по ссылке — для их независимости нужно глубокое копирование.

Как скопировать структуру, если заранее неизвестны её ключи?

Перебором: создайте пустую структуру и в цикле Для Каждого Элемент Из Источник выполняйте Результат.Вставить(Элемент.Ключ, Элемент.Значение). Этот способ не требует знания состава ключей.

Чем отличается структура от соответствия при копировании?

Механика копирования одинакова — перебор или сериализация. Разница в исходном типе: у структуры ключи-идентификаторы, у соответствия ключами могут быть любые значения. ПрочитатьJSON по умолчанию возвращает соответствие, что нужно учитывать при десериализации.

Как скопировать только часть ключей структуры?

Передайте список нужных свойств третьим параметром: ЗаполнитьЗначенияСвойств(Приемник, Источник, "Имя,Сумма"). Либо при переборе добавьте условие по имени ключа — например, копировать только ключи с определённым префиксом.