При разработке универсальных обработок или сложных алгоритмов в 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]"
Значение = Шаблон("[ТоварА." + ИмяПоля + "]");
Сообщить(Значение);
Хотя этот метод рабочий, мы не рекомендуем использовать его для обычного получения атрибутов. Он работает значительно медленнее, чем ПолучитьАтрибут(), и его сложнее отлаживать. Однако он может быть полезен, если вам нужно вычислить сложное выражение или вызвать функцию, имя которой также динамическое.
Для тех, кто переходит с версии 7.7 на 8.3 или наоборот, важно понимать разницу. В восьмой версии платформы разработчики упростили этот механизм. Вместо вызова специальных методов можно использовать оператор квадратные скобки [], который работает как для реквизитов, так и для элементов коллекций:
В 1С 8.х: Значение = Объект[ИмяРеквизита];
В 1С 7.7: Значение = Объект.ПолучитьАтрибут(ИмяРеквизита);
Проанализируем несколько важных нюансов, которые помогут писать более качественный код:
ТоварА.price) всегда быстрее, чем вызов ПолучитьАтрибут(). Если имена полей заранее известны, используйте прямое обращение. Применяйте динамический доступ только там, где это действительно необходимо.Форма.ПолучитьАтрибут(ИмяЭлемента).Подведем итог: для динамического управления данными в 1С 7.7 используйте связку ПолучитьАтрибут() и УстановитьАтрибут(). Это стандартный, надежный и наиболее быстрый способ решения задачи подстановки имени реквизита из переменной.