Как получить код периодического ссылочного реквизита справочника в 1С 7.7?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При разработке отчетов и обработок в платформе 1С:Предприятие 7.7 часто возникает необходимость получить данные из связанных справочников. Типичная задача: у справочника (например, Сотрудники) есть периодический реквизит (например, Должность), который ссылается на другой справочник (Подразделения или Должности). Разработчику требуется получить не строковое представление, а конкретный системный реквизит — Код элемента связанного справочника на определенную дату.

При попытке напрямую обратиться к коду через конструкцию вида спр.Должность.Код.Получить(ДатаДок) или спр.Должность.Получить(ДатаДок).Код платформа нередко выдает ошибку времени выполнения «Поле агрегатного объекта не обнаружено (Код)». Разберем причины такого поведения и рассмотрим правильные варианты реализации выборки данных.

Выясним причину возникновения ошибки:

  1. Неверная последовательность обращения к свойствам. Реквизит Код у подчиненного справочника является постоянным (непериодическим), в то время как реквизит Должность в основном справочнике — периодический. Конструкция спр.Должность.Код.Получить() синтаксически неверна, так как метод Получить() вызывается у реквизита Код, который не имеет истории значений.
  2. Обращение к реквизитам пустого значения. Если на указанную дату значение периодического реквизита не заполнено, метод Получить(ДатаДок) вернет пустое значение. Попытка взять свойство .Код у пустого объекта неизбежно приводит к аварийному завершению работы модуля.
  3. Ограничения цепочек вызовов в 1С 7.7. В ряде случаев платформа 1С 7.7 некорректно обрабатывает обращение к свойствам через точку сразу после вызова функции в одной строке без сохранения промежуточного результата.

Способ 1. Позиционирование объекта на дату с помощью метода «ИспользоватьДату()»

Наиболее лаконичный и быстрый способ обхода выборки элементов с периодическими реквизитами — предварительная установка рабочей даты для объекта справочника. Когда мы вызываем метод ИспользоватьДату() до начала выборки, платформа автоматически считывает все периодические реквизиты на заданный момент времени при вызове метода ПолучитьЭлемент().

Рассмотрим пример кода:


Процедура Сформировать()
    Перем спр;
    спр = СоздатьОбъект("Справочник.Сотрудники");
    
    // Устанавливаем дату для считывания периодических реквизитов (второй параметр 0 — режим чтения)
    спр.ИспользоватьДату(ДатаДок, 0);
    спр.ВыбратьЭлементы();
    
    Пока спр.ПолучитьЭлемент() > 0 Цикл
        // Проверяем, что ссылка на элемент заполнена
        Если спр.Должность.Выбран() = 1 Тогда
            Сообщить("Сотрудник: " + спр.Наименование + " | Код должности: " + спр.Должность.Код);
        Иначе
            Сообщить("Сотрудник: " + спр.Наименование + " | Должность не указана!");
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

В этом варианте обращение к спр.Должность.Код происходит напрямую, так как контекст периодичности уже определен вызовом ИспользоватьДату().

Способ 2. Получение значения в промежуточную переменную с проверкой на заполненность

Если дату необходимо динамически менять в теле цикла или требуется точечно получить значение реквизита без смены контекста всего справочника, разберем подход с выгрузкой значения во временную переменную.

Посмотрим на пример безопасного извлечения кода:


Процедура Сформировать()
    Перем спр, ТекЗначение;
    спр = СоздатьОбъект("Справочник.Сотрудники");
    спр.ВыбратьЭлементы();
    
    Пока спр.ПолучитьЭлемент() > 0 Цикл
        // Получаем периодическое значение на конкретную дату в переменную
        ТекЗначение = спр.Должность.Получить(ДатаДок);
        
        // Обязательно проверяем значение перед обращением к реквизитам
        Если ПустоеЗначение(ТекЗначение) = 0 Тогда
            Если ТекЗначение.Выбран() = 1 Тогда
                Сообщить("Код: " + ТекЗначение.Код + " | Наименование: " + ТекЗначение.Наименование);
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Такой подход полностью защищает от ошибки «Поле агрегатного объекта не обнаружено», так как обращение к свойству .Код происходит только в том случае, если переменная действительно содержит ссылку на существующий элемент справочника.

Способ 3. Использование системного объекта «Периодический»

Для явной работы с историей периодических реквизитов в 1С 7.7 предусмотрен специальный объект метаданных Периодический. Он позволяет точно управлять срезом значений и датами установки.

Проанализируем пример работы с объектом Периодический:


Процедура Сформировать()
    Перем спр, ОбьектПериодический, ЗначРеквизита;
    
    спр = СоздатьОбъект("Справочник.Сотрудники");
    ОбьектПериодический = СоздатьОбъект("Периодический");
    
    спр.ВыбратьЭлементы();
    Пока спр.ПолучитьЭлемент() > 0 Цикл
        // Привязываем объект к периодическому реквизиту текущего элемента
        ОбьектПериодический.ИспользоватьОбъект("Должность", спр.ТекущийЭлемент());
        
        Если ОбьектПериодический.Получить(ДатаДок) = 1 Тогда
            ЗначРеквизита = ОбьектПериодический.Значение;
            Если ПустоеЗначение(ЗначРеквизита) = 0 Тогда
                Сообщить("Сотрудник: " + спр.Наименование + " | Код: " + ЗначРеквизита.Код);
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Итог: Чтобы избежать ошибок при извлечении реквизитов связанных справочников в 1С 7.7, всегда разделяйте этап получения периодического значения и этап обращения к свойствам полученного объекта, либо используйте метод ИспользоватьДату() до открытия выборки элементов.

← На главную