При обходе метаданных объектов конфигурации часто возникает необходимость отфильтровать реквизиты по конкретному типу данных — например, найти все поля табличной части, имеющие тип ХранилищеЗначения. Рассмотрим, как правильно выполнять такую проверку программно, какие ошибки могут возникнуть при работе с отладчиком и как корректно копировать данные бинарных хранилищ.
Для определения состава типов реквизита в 1С применяется объект ОписаниеТипов. Чтобы проверить, содержит ли реквизит табличной части справочника или документа тип ХранилищеЗначения, используем метод СодержитТип() объекта ОписаниеТипов.
Разберем рабочий пример обхода всех табличных частей объекта метаданных:
Для Каждого мдТЧ Из Метаданные().ТабличныеЧасти Цикл
Для Каждого мдРеквизит Из мдТЧ.Реквизиты Цикл
Если мдРеквизит.Тип.СодержитТип(Тип("ХранилищеЗначения")) Тогда
// Реквизит имеет тип ХранилищеЗначения
Сообщить("Найден реквизит ТЧ: " + мдТЧ.Имя + "." + мдРеквизит.Имя);
КонецЕсли;
КонецЦикла;
КонецЦикла;
Также проверить доступные типы реквизита можно путем получения массива типов с помощью метода Типы():
МассивТипов = мдРеквизит.Тип.Типы();
Для Каждого ТекущийТип Из МассивТипов Цикл
Если ТекущийТип = Тип("ХранилищеЗначения") Тогда
// Выполняем нужные действия
КонецЕсли;
КонецЦикла;
Иногда при отладке кода разработчик может столкнуться со ситуацией, когда выражение мдРеквизит.Тип.СодержитТип(Тип("ХранилищеЗначения")) возвращает Ложь, хотя в конфигураторе реквизит воспринимается как хранилище. Проанализируем возможные причины этого поведения:
СпособПредоставления и реквизит хранения настроек НастройкиСпособа). Если в отладчике случайно указать имя ссылочного поля, массив Типы() вернет тип ссылки или перечисления, а не ХранилищеЗначения.Типы() вернет список всех входящих типов. Метод СодержитТип() в таком случае вернет Истина, только если нужный тип входит в составное описание.При дублировании строк табличной части или копировании объекта справочника недостаточно просто скопировать значение реквизита через ЗаполнитьЗначенияСвойств(), так как это приведет к копированию ссылки на тот же внутренний объект хранилища. Чтобы настройки или файлы в объекте-приемнике были независимы от источника, их необходимо пересоздавать.
Рассмотрим правильный алгоритм переноса данных:
// Извлекаем значение из исходного хранилища
ЗначениеХранилища = СтрокаИсточника.РеквизитХранилище.Получить();
// Создаем новое хранилище для строки-приемника
СтрокаПриемника.РеквизитХранилище = Новый ХранилищеЗначения(ЗначениеХранилища, Новый СжатиеДанных());
При использовании полей типа ХранилищеЗначения внутри табличных частей необходимо учитывать следующие технические особенности платформы 1С:
ХранилищеЗначения нельзя использовать в условиях ГДЕ, ГРУППИРОВАТЬ ПО и УПОРЯДОЧИТЬ ПО языка запросов.ПоместитьВоВременноеХранилище().