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