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

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

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

Почему возникает ошибка «НеизвестныйОбъект» при обращении к форме?

Рассмотрим типичную ошибку начинающих разработчиков. Пытаясь получить значение активного элемента формы по его имени, программист пишет следующий код:


Процедура ЗначениеДай()
    ИмяРеквизита = Форма.АктивныйЭлемент(); 
    Сообщить(Форма.ПолучитьАтрибут(ИмяРеквизита)); // Выдает ошибку: "НеизвестныйОбъект"
КонецПроцедуры

Давайте проанализируем ситуацию и выясним причину такого поведения платформы. Всё дело в архитектуре контекста встроенного языка 1С 7.7:

  1. Методы ПолучитьАтрибут() и УстановитьАтрибут() принадлежат прикладному объекту (например, элементу справочника или документу), а не самому объекту Форма.
  2. В модуле формы справочника или документа мы уже находимся в контексте самого этого прикладного объекта. Обращение к его реквизитам и методам происходит напрямую, без каких-либо префиксов.
  3. Системный объект Форма в 1С 7.7 имеет крайне ограниченный набор собственных методов (таких как АктивныйЭлемент(), Закрыть(), ТолькоПросмотр()). Метода ПолучитьАтрибут() у объекта Форма просто не существует, поэтому платформа и возвращает ошибку «НеизвестныйОбъект».

Правильный способ получения значения реквизита по имени

Чтобы успешно прочитать значение реквизита по его строковому представлению, нам достаточно просто убрать обращение к объекту Форма и вызвать метод напрямую. Платформа автоматически поймет, что поиск атрибута должен производиться в контексте текущего открытого объекта.

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


Процедура ЗначениеДай()
    // Получаем имя активного элемента формы (например, "Телефон1")
    ИмяРеквизита = Форма.АктивныйЭлемент(); 
    
    // Получаем значение реквизита напрямую из контекста модуля формы
    ЗначениеРеквизита = ПолучитьАтрибут(ИмяРеквизита);
    
    Сообщить("Значение активного реквизита: " + ЗначениеРеквизита);
КонецПроцедуры

Этот способ отлично работает для чтения простых типов данных (строк, чисел, дат). Однако, когда дело доходит до записи значений, разработчики сталкиваются со следующим серьезным ограничением платформы.

Проблема изменения (записи) значения по имени

Штатный метод УстановитьАтрибут(Имя, Значение) в 1С 7.7 имеет жесткое ограничение: он корректно работает только для тех прикладных объектов, которые были созданы программно через функцию СоздатьОбъект(). Попытка вызвать этот метод напрямую в модуле открытой формы для изменения текущего редактируемого элемента вызовет ошибку или просто проигнорируется платформой.

Тем не менее, существует два проверенных обходных пути («хака»), которые активно использовались разработчиками для решения этой задачи.

Решение №1: Обход ограничения через передачу Контекста

Это красивое и лаконичное решение основано на недокументированной особенности работы с типом данных Контекст. Если передать системное ключевое слово Контекст во внешнюю функцию и вернуть его обратно, платформа выполняет неявное приведение типов, «разблокируя» возможность использования метода УстановитьАтрибут() для экранной формы.

Разберем реализацию этого метода по шагам:

Шаг 1. Создаем вспомогательную функцию-транзистор (ее можно разместить прямо в модуле формы или в глобальном модуле):


Функция ВзятьКонтекст(Конт)
    Возврат Конт;
КонецФункции

Шаг 2. В нужном месте модуля формы используем полученный контекст для изменения значения:


Процедура УстановитьЗначениеПоИмени(ИмяРеквизита, НовоеЗначение)
    // Получаем "разблокированный" контекст формы
    Конт = ВзятьКонтекст(Контекст);
    
    // Теперь метод УстановитьАтрибут отработает корректно!
    Конт.УстановитьАтрибут(ИмяРеквизита, НовоеЗначение);
КонецПроцедуры

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

Решение №2: Динамическое выполнение кода через функцию Шаблон()

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

Для чтения сложных типов данных (например, справочников или документов) обычный вызов Шаблон("[" + ИмяРеквизита + "]") вернет лишь строковое представление объекта, что непригодно для дальнейшей работы. Чтобы получить полноценную ссылку на объект, мы можем использовать преобразование через внутренний формат системы:


// Динамическое получение объекта любого типа по имени реквизита
Значение = ЗначениеИзСтрокиВнутр(Шаблон("[ЗначениеВСтрокуВнутр(" + ИмяРеквизита + ")]"));

Для динамической записи значения по его имени с помощью шаблонов нам понадобится простая функция-посредник, которая принимает параметры по ссылке и перезаписывает их:


Функция УстАтрибут(Атр, Зн)
    Атр = Зн;
    Возврат "";
КонецФункции

После этого мы можем изменить значение реквизита всего одной строкой кода:


// Динамически записываем НовоеЗначение в реквизит, имя которого хранится в ИмяРеквизита
Шаблон("[УстАтрибут(" + ИмяРеквизита + ", НовоеЗначение)]");

При расчете этого шаблона платформа подставляет в функцию УстАтрибут сам реквизит формы, передает его по ссылке и успешно перезаписывает новым значением.

Как аналогичная задача решается в платформе 1С:Предприятие 8

Разработчики новой платформы полностью избавились от подобных архитектурных сложностей и ограничений контекста. В 1С 8 методы ПолучитьАтрибут() и УстановитьАтрибут() были упразднены за ненадобностью.

Вместо этого была добавлена универсальная возможность обращаться к свойствам и реквизитам любых объектов, коллекций и форм по их строковому имени с помощью квадратных скобок []. Посмотрим, насколько проще стал код:


// Получение значения по имени в 1С 8.3
Значение = Объект[ИмяРеквизита];

// Установка значения по имени в 1С 8.3
Объект[ИмяРеквизита] = НовоеЗначение;

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

← На главную