Как в 1С 7.7 узнать значение реквизита, если его имя хранится в переменной?

Программист 1С v7.7
← На главную

При разработке универсальных обработок или сложных алгоритмов в 1С:Предприятии 7.7 программисты часто сталкиваются с ситуацией, когда имя реквизита (например, наименование поля справочника) становится известным только во время выполнения программы. Это может быть выбор из списка, получение данных из перечисления или чтение настроек из внешнего файла. Рассмотрим, как правильно реализовать динамическое обращение к данным, и выясним, почему стандартное обращение через «точку» в этом случае не работает.

Проблема: Почему прямое обращение через переменную вызывает ошибку?

Разберем ситуацию, описанную автором вопроса. Предположим, у нас есть справочник ТоварыАвто с реквизитом price. Когда мы пишем код Сообщить(ТоварА.price);, платформа на этапе компиляции понимает, что нужно обратиться к конкретному полю. Однако, если мы попытаемся подставить переменную:


ПеременнаяЦена = "price";
Сообщить(ТоварА.ПеременнаяЦена); // Ошибка!

Проанализируем причину возникновения ошибки «Поле агрегатного объекта не обнаружено». Система ищет у объекта ТоварА реквизит, который буквально называется «ПеременнаяЦена». Она не воспринимает это слово как ссылку на содержимое строковой переменной. В 1С 7.7, в отличие от более современных версий платформы, синтаксис обращения к свойствам объектов строго типизирован и не поддерживает автоматическую подстановку имен через переменные в стандартной нотации через точку.

Основное решение: Использование метода ПолучитьАтрибут()

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


ТоварА = СоздатьОбъект("Справочник.ТоварыАвто");
ТоварА.ВыбратьЭлементы();
Пока ТоварА.ПолучитьЭлемент() = 1 Цикл
    ПеременнаяЦена = "price";
    // Используем специальный метод для доступа по имени
    ЗначениеЦены = ТоварА.ПолучитьАтрибут(ПеременнаяЦена);
    Сообщить("Цена товара: " + ЗначениеЦены);
КонецЦикла;

Этот метод принимает строковый параметр (идентификатор реквизита) и возвращает его значение. Важно помнить, что если вы ошибетесь в написании имени реквизита внутри строки, программа также выдаст ошибку, но уже в момент выполнения (Runtime), а не на этапе проверки синтаксиса.

Запись данных: Метод УстановитьАтрибут()

Разберем обратную ситуацию: нам нужно не просто прочитать данные, а изменить их, используя имя реквизита из переменной. Для этого используется парный метод УстановитьАтрибут(). Рассмотрим на примере:


ИмяРеквизита = "price";
НоваяЦена = 1500;
ТоварА.УстановитьАтрибут(ИмяРеквизита, НоваяЦена);
ТоварА.Записать();

Важный момент: динамическая установка атрибутов работает точно так же, как и прямая. После изменения значения не забудьте вызвать метод Записать(), если работаете с объектом базы данных (справочником или документом), иначе изменения останутся только в оперативной памяти.

Автоматический перебор всех реквизитов через Метаданные

Часто задача стоит шире: не просто обратиться к одному полю, а перебрать все доступные реквизиты объекта. Выясним, как это сделать правильно. В 1С 7.7 информация о структуре данных хранится в объекте Метаданные. Проанализируем пример цикла, который выводит значения всех реквизитов справочника:


СпрОбъект = СоздатьОбъект("Справочник.ТоварыАвто");
Если СпрОбъект.НайтиПоКоду("00001") = 1 Тогда
    // Получаем количество реквизитов справочника из метаданных
    КолвоРеквизитов = Метаданные.Справочник("ТоварыАвто").Реквизит();
    
    Для и = 1 По КолвоРеквизитов Цикл
        ИмяПоля = Метаданные.Справочник("ТоварыАвто").Реквизит(и).Идентификатор;
        ЗначениеПоля = СпрОбъект.ПолучитьАтрибут(ИмяПоля);
        Сообщить(ИмяПоля + " = " + ЗначениеПоля);
    КонецЦикла;
КонецЕсли;

Такой подход позволяет создавать по-настоящему универсальные инструменты, например, обработки для выгрузки данных в Excel или XML, которые не потребуют правки кода при добавлении новых реквизитов в конфигураторе.

Альтернативный способ: Функция Шаблон()

Существует еще один, более экзотический способ получения значения через текстовую строку — использование функции Шаблон(). Эта функция вычисляет выражения, заключенные в квадратные скобки внутри строки. Рассмотрим пример:


ИмяПоля = "price";
// Формируем строку вида "[ТоварА.price]"
Значение = Шаблон("[ТоварА." + ИмяПоля + "]");
Сообщить(Значение);

Хотя этот метод рабочий, мы не рекомендуем использовать его для обычного получения атрибутов. Он работает значительно медленнее, чем ПолучитьАтрибут(), и его сложнее отлаживать. Однако он может быть полезен, если вам нужно вычислить сложное выражение или вызвать функцию, имя которой также динамическое.

Сравнение с 1С 8.х

Для тех, кто переходит с версии 7.7 на 8.3 или наоборот, важно понимать разницу. В восьмой версии платформы разработчики упростили этот механизм. Вместо вызова специальных методов можно использовать оператор квадратные скобки [], который работает как для реквизитов, так и для элементов коллекций:

В 1С 8.х: Значение = Объект[ИмяРеквизита];

В 1С 7.7: Значение = Объект.ПолучитьАтрибут(ИмяРеквизита);

Особенности производительности и рекомендации

Проанализируем несколько важных нюансов, которые помогут писать более качественный код:

  1. Скорость выполнения: Прямое обращение через точку (ТоварА.price) всегда быстрее, чем вызов ПолучитьАтрибут(). Если имена полей заранее известны, используйте прямое обращение. Применяйте динамический доступ только там, где это действительно необходимо.
  2. Работа с формой: Эти же методы работают и для элементов диалога. Если вам нужно программно изменить доступность или видимость поля на форме, имя которого хранится в переменной, используйте Форма.ПолучитьАтрибут(ИмяЭлемента).
  3. Проверка на существование: Чтобы программа не завершилась аварийно при отсутствии реквизита, в критически важных местах рекомендуется проверять наличие атрибута через метаданные перед его получением.

Подведем итог: для динамического управления данными в 1С 7.7 используйте связку ПолучитьАтрибут() и УстановитьАтрибут(). Это стандартный, надежный и наиболее быстрый способ решения задачи подстановки имени реквизита из переменной.

← На главную