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