При разработке внешних печатных форм или обработок в 1С часто возникает задача извлечения данных, которые не являются стандартными реквизитами объекта, а вынесены в так называемые «Дополнительные реквизиты и сведения». Одной из типичных проблем является получение ФИО директора контрагента, если эти данные хранятся как свойство. В процессе реализации программисты часто сталкиваются с ошибкой Итератор для значения не определен. Рассмотрим подробно, почему возникает эта ошибка и как правильно извлекать дополнительные реквизиты, используя современные стандарты разработки в 1С.
Разберем ситуацию, представленную в коде автора темы. Ошибка Итератор для значения не определен возникает в строке Для Каждого Стр из СсылкаНаОбъект Цикл. В языке 1С конструкция Для каждого ... из ... предназначена исключительно для работы с коллекциями данных: массивами, таблицами значений, табличными частями или соответствиями.
Проанализируем тип переменной СсылкаНаОбъект. Если в процедуру печати передается одиночная ссылка на справочник (например, СправочникСсылка.Партнеры), то она не является коллекцией. Попытка применить к ней цикл приводит к немедленной остановке программы. Если ваша задача — обработать только один объект, цикл не нужен вовсе. Если же объектов несколько, необходимо убедиться, что СсылкаНаОбъект является массивом или списком значений.
Важное правило: Перед использованием цикла всегда проверяйте тип данных или убедитесь, что логика формирования коллекции в вызывающем коде соответствует вашим ожиданиям.
Если нам известно, что данные «Директора» хранятся именно в дополнительных реквизитах контрагента, мы можем обратиться к табличной части ДополнительныеРеквизиты. Рассмотрим исправленный код автора без использования ошибочного цикла:
// Сначала найдем само свойство (вид характеристики)
ДопСвойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Директор");
// Проверяем, что свойство найдено, чтобы избежать ошибки при поиске в коллекции
Если Не ДопСвойство.Пустая() Тогда
// Обращаемся к контрагенту через партнера
СтрокаСвойства = СсылкаНаОбъект.Контрагент.ДополнительныеРеквизиты.Найти(ДопСвойство, "Свойство");
Если СтрокаСвойства <> Неопределено Тогда
// Получаем значение (это может быть строка или ссылка на значение свойства)
ДиректорЗначение = СтрокаСвойства.Значение;
ОбластьШапкиДанных.Параметры.Пункт0_4 = Строка(ДиректорЗначение);
КонецЕсли;
КонецЕсли;
В этом примере мы проанализировали структуру метаданных. У объекта Контрагент есть табличная часть ДополнительныеРеквизиты, где в колонке Свойство хранится ссылка на план видов характеристик, а в колонке Значение — нужные нам данные.
В типовых конфигурациях (УТ 11, ERP 2.5, КА 2.5, БП 3.0) реализована «Библиотека стандартных подсистем» (БСП). Она предоставляет программный интерфейс для работы с доп. свойствами, который гораздо надежнее и проще в использовании. Вместо того чтобы вручную перебирать табличные части, рекомендуется использовать общий модуль УправлениеСвойствами.
Выясним преимущества этого метода: вам не нужно знать, где именно хранится реквизит (в табличной части объекта или во внешнем регистре сведений ДополнительныеСведения). Система сама определит местоположение данных.
Пример использования функции БСП:
// Определяем свойство
ДопСвойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Директор");
// Получаем значение через стандартный механизм БСП
Директор = УправлениеСвойствами.ЗначениеРеквизита(СсылкаНаОбъект.Контрагент, ДопСвойство);
// Выводим результат
Если ЗначениеЗаполнено(Директор) Тогда
ОбластьШапкиДанных.Параметры.Пункт0_4 = Строка(Директор);
КонецЕсли;
Функция УправлениеСвойствами.ЗначениеРеквизита принимает два параметра: ссылку на объект (Контрагент) и ссылку на свойство. Это сокращает ваш код и делает его устойчивым к изменениям структуры конфигурации.
Рассмотрим критические замечания, высказанные в обсуждении. Использование НайтиПоНаименованию("Директор") — это «хрупкое» решение. Если пользователь создаст еще одно свойство с таким же именем для другого справочника или переименует текущее, код перестанет работать.
Рекомендации по улучшению кода:
Найти() или ЗначениеРеквизита() на Неопределено или ПустаяСсылка.ЗначенияСвойствОбъектов. Функция Строка() поможет получить текстовое представление, но для сложных печатных форм может потребоваться обращение к реквизитам этого справочника.Ссылка.Контрагент...) в цикле крайне неэффективно. В этом случае лучше использовать один запрос к базе данных, соединяясь с таблицей дополнительных реквизитов.Если данные не возвращаются, как в случае автора (сообщение 5), проанализируем ситуацию с помощью отладки. Проверьте следующие моменты:
Подводя итог, для решения задачи необходимо четко разделять коллекции и одиночные ссылки, отдавать предпочтение методам БСП и минимизировать использование поиска по текстовому наименованию в пользу более надежных идентификаторов объектов.