Разработка и Конфигурация · 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 требует больше кода и медленнее.
Полный контроль над копированием любых вложенностей. Ограничение: нужно вручную обрабатывать все типы коллекций.
Копирование структуры в объект конфигурации
Частая практическая задача — перенести данные из структуры в объект справочника или документа. Здесь ЗаполнитьЗначенияСвойств работает особенно удобно: она сопоставляет ключи структуры с реквизитами объекта по именам.
Данные = Новый Структура("Наименование,ИНН,КПП", "ООО Ромашка", "7700000000", "770001001");
НовыйКонтрагент = Справочники.Контрагенты.СоздатьЭлемент();
ЗаполнитьЗначенияСвойств(НовыйКонтрагент, Данные);
НовыйКонтрагент.Записать();
Ключи, которых нет среди реквизитов объекта, игнорируются — ошибки не возникает. Это позволяет использовать одну структуру-источник для заполнения разных объектов. Обратная операция — выгрузка реквизитов объекта в структуру — делается через перебор метаданных объекта или через ЗаполнитьЗначенияСвойств(Структура, Объект) с заранее подготовленным набором ключей.
Проверка результата и типичные ошибки
После копирования убедитесь, что получен независимый объект: измените значение в копии и проверьте, что оригинал не изменился. Для вложенных структур проверьте отдельно — именно на вложенном уровне чаще всего обнаруживается, что копия была поверхностной.
Сравнить две структуры на равенство оператором = нельзя — для объектов он сравнивает ссылки, а не содержимое. Для сравнения содержимого перебирайте ключи и сравнивайте значения поэлементно или сериализуйте обе структуры в JSON и сравните строки.
Выбор способа под задачу
Для простых плоских структур с известным набором ключей достаточно ЗаполнитьЗначенияСвойств — это самый читаемый вариант. Если приёмник пустой или нужна фильтрация значений, используйте перебор. Для независимой копии сложной вложенной структуры — сериализацию или рекурсию.
Как выбрать способ
В прикладных решениях часто встречается готовая функция общего модуля — в типовых конфигурациях это ОбщегоНазначения.СкопироватьРекурсивно() или аналогичные методы. Перед написанием собственного велосипеда проверьте, нет ли подходящей функции в стандартных подсистемах вашей конфигурации.
Что важно запомнить
Простое присваивание не копирует структуру, а создаёт вторую ссылку. Для плоских структур используйте ЗаполнитьЗначенияСвойств или перебор, для вложенных — сериализацию или рекурсию. После копирования проверяйте независимость копии изменением тестового значения.
Частые вопросы
Можно ли скопировать структуру одной строкой?
Да, если приёмник уже содержит нужные ключи: ЗаполнитьЗначенияСвойств(Приемник, Источник). Для пустого приёмника одной встроенной команды нет — потребуется цикл перебора или вызов собственной функции копирования.
Почему после копирования изменения в копии видны и в оригинале?
Либо вы присвоили структуру через «=» (получили вторую ссылку на тот же объект), либо выполнили поверхностное копирование, а изменяете вложенную структуру или массив. Вложенные объекты копируются по ссылке — для их независимости нужно глубокое копирование.
Как скопировать структуру, если заранее неизвестны её ключи?
Перебором: создайте пустую структуру и в цикле Для Каждого Элемент Из Источник выполняйте Результат.Вставить(Элемент.Ключ, Элемент.Значение). Этот способ не требует знания состава ключей.
Чем отличается структура от соответствия при копировании?
Механика копирования одинакова — перебор или сериализация. Разница в исходном типе: у структуры ключи-идентификаторы, у соответствия ключами могут быть любые значения. ПрочитатьJSON по умолчанию возвращает соответствие, что нужно учитывать при десериализации.
Как скопировать только часть ключей структуры?
Передайте список нужных свойств третьим параметром: ЗаполнитьЗначенияСвойств(Приемник, Источник, "Имя,Сумма"). Либо при переборе добавьте условие по имени ключа — например, копировать только ключи с определённым префиксом.