Как в 1С 7.7 выполнить обращение к переменной или функции, если их имя задано строкой?

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

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

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

Способ 1. Штатная функция Шаблон() и обход ее ограничений

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

Однако, как справедливо замечено, у этого метода есть два существенных недостатка:

  1. Функция всегда возвращает результат типа Строка.
  2. Если внутри шаблона возникает ошибка (например, переменная не найдена), платформа выводит модальное окно с ошибкой, которое трудно перехватить конструкцией Попытка ... Исключение.

Разберем, как можно обойти ограничение по типу возвращаемого значения. Для этого применяется техника "двойной сериализации". Суть метода заключается в том, чтобы внутри шаблона преобразовать значение во внутреннюю строку, вернуть её, а затем восстановить значение.

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


// Функция для получения значения переменной по её имени (Строка)
Функция ПолучитьЗначениеПоИмени(ИмяПеременной)
    // Формируем выражение для шаблона:
    // [ЗначениеВСтрокуВнутр(ИмяПеременной)]
    ТекстШаблона = "[ЗначениеВСтрокуВнутр(" + ИмяПеременной + ")]";
    
    // Выполняем шаблон. Результатом будет строковое представление значения
    СтрЗначение = Шаблон(ТекстШаблона);
    
    // Восстанавливаем значение из внутренней строки
    Возврат ЗначениеИзСтрокиВнутр(СтрЗначение);
КонецФункции

Этот метод работает, если переменная существует. Если переменной нет, Шаблон все равно выдаст ошибку в окно сообщений, и программно скрыть её штатно крайне сложно.

Способ 2. Использование внешней компоненты 1С++

Для более серьезных задач, где требуется надежная обработка ошибок и выполнение произвольных алгоритмов, стандартом де-факто для 7.7 является использование внешней компоненты 1С++ (1cpp.dll). Она предоставляет объект ВыполняемыйМодуль, который позволяет динамически компилировать и выполнять код.

Рассмотрим, как с помощью 1С++ создать универсальную функцию для получения значения переменной контекста. Этот метод позволяет избежать ошибок интерфейса, так как мы можем программно сформировать текст модуля.

Пример реализации функции чтения переменной:


Функция ПеременнаяКонтекста(Конт, ИмяПеременной) Экспорт
    // Формируем текст модуля динамически
    // Мы создаем функцию, которая просто возвращает нужное нам значение
    ТекстМодуля = "
    |Функция ПолучитьЗначение()
    |    Возврат " + ИмяПеременной + ";
    |КонецФункции
    |";
    
    // Создаем объект ВыполняемыйМодуль из компоненты 1С++
    Модуль = СоздатьОбъект("ВыполняемыйМодуль");
    
    // Передаем текст нашего микро-модуля
    Модуль.УстановитьМодуль(ТекстМодуля);
    
    // Назначаем контекст, в котором должна искаться переменная (обычно это контекст формы или глобальный)
    Модуль.НазначитьКонтекст(Конт);
    
    // Компилируем и выполняем (инициализируем) модуль
    Модуль.КомпилироватьМодуль();
    Модуль.ВыполнитьМодуль();
    
    // Вызываем нашу динамически созданную функцию
    Возврат Модуль.ПолучитьЗначение();
КонецФункции

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


Функция УстановитьПеременную(Конт, ИмяПеременной, Значение) Экспорт
    ТекстМодуля = "
    |Функция УстЗнач(НовоеЗначение)
    |    " + ИмяПеременной + " = НовоеЗначение;
    |    Возврат " + ИмяПеременной + ";
    |КонецФункции
    |";
    
    Модуль = СоздатьОбъект("ВыполняемыйМодуль");
    Модуль.УстановитьМодуль(ТекстМодуля);
    Модуль.НазначитьКонтекст(Конт);
    Модуль.КомпилироватьМодуль();
    Модуль.ВыполнитьМодуль();
    
    Возврат Модуль.УстЗнач(Значение);
КонецФункции

Преимущества метода 1С++:

Способ 3. Использование внешней компоненты FormEx

Еще одна популярная компонента FormEx предоставляет объект Сервис, который также умеет выполнять функции контекста по имени. Этот способ немного проще, если вам нужно только вызвать процедуру или функцию, а не компилировать сложный код.

Пример вызова функции:


// Подключаем объект Сервис
оСервис = СоздатьОбъект("Сервис");
Рез = 0; // Переменная для результата

// Выполняем функцию
// Конт - контекст формы или модуля
// ИмяМетода - строковое имя функции
// сзАрг - список значений с аргументами (если есть)
// Рез - сюда вернется результат выполнения
оСервис.ВыполнитьФункцию(Конт, ИмяМетода, сзАрг, Рез);

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

Особенности работы с Глобальным Модулем

Важно отметить, что доступ к переменным Глобального Модуля (ГМ) имеет свои нюансы. Стандартный Шаблон() видит экспортные переменные ГМ. Однако, если вы хотите проверить существование переменной или функции в ГМ без риска получить ошибку, лучше использовать ВыполняемыйМодуль.

В сложных сценариях (как показано в одном из примеров темы) используется комбинированный подход: сначала проверяется наличие загруженных компонент, а затем через MSScriptControl или ВыполняемыйМодуль происходит попытка обратиться к переменной. Это позволяет писать универсальный код, который не "валится" при отсутствии переменной.

Резюме

Подведем итог выбора инструмента для решения задачи:

  1. Если задача простая (только чтение), и вы уверены, что переменная существует — используйте Шаблон() с трюком ЗначениеИзСтрокиВнутр.
  2. Если нужно полноценное динамическое выполнение кода, работа с контекстом, запись переменных или безопасная проверка существования — используйте 1С++ (ВыполняемыйМодуль).
  3. Если нужно просто вызвать функцию по имени из доступного контекста — подойдет FormEx.
← На главную