В разработке на платформе 1С:Предприятие 7.7 программисты часто сталкиваются с ограничением: встроенный язык не поддерживает прямой аналог команды Выполнить(), которая появилась в версии 8.х. Если имя процедуры заранее неизвестно и хранится в строковой переменной (например, при реализации планировщика задач или универсального обработчика событий), стандартные средства вызова «в лоб» не срабатывают. Особенно остро этот вопрос встает при попытке использовать внешние компоненты, такие как FormEx.
В данной статье мы подробно разберем, как обойти архитектурные ограничения «клюшек», проанализируем возможности внешних компонент и выберем оптимальный способ вызова процедур глобального модуля по их имени.
Рассмотрим ситуацию, когда разработчик пытается использовать объект Сервис из библиотеки FormEx. Метод ВыполнитьПроцедуру() кажется идеальным решением, однако он имеет существенную особенность: он работает с контекстом. По умолчанию, если контекст не передан, поиск процедуры происходит в локальном модуле текущей формы или обработки.
Проблема в том, что «Глобальный контекст» в 1С 7.7 не является объектом, который можно легко передать в параметре. Поэтому попытка выполнить код:
Сервис = СоздатьОбъект("Сервис");
ПутьОбработчика = "МояГлобальнаяПроцедура";
Сервис.ВыполнитьПроцедуру( , ПутьОбработчика);
закончится неудачей, даже если процедура помечена ключевым словом Экспорт. Система просто не «видит» глобальный модуль из этого вызова. Для решения задачи нам придется рассмотреть более продвинутые инструменты или «хитрости» штатного языка.
Если в вашей конфигурации используется мощная библиотека 1С++, то наиболее правильным и профессиональным способом будет использование класса ВыполняемыйМодуль. Этот объект позволяет компилировать и исполнять произвольный код на языке 1С прямо во время работы программы.
Разберем алгоритм работы с этим объектом по шагам:
ВыполняемыйМодуль.Пример кода будет выглядеть следующим образом:
// Предположим, ИмяПроц - это переменная со строкой "ГлОбработкаДанных"
ВМ = СоздатьОбъект("ВыполняемыйМодуль");
ТекстКода = ИмяПроц + "();"; // Формируем строку вызова
ВМ.УстановитьМодуль(ТекстКода);
ВМ.КомпилироватьИВыполнитьМодуль();
Преимущество этого метода заключается в том, что динамически скомпилированный код исполняется в окружении, где доступны все экспортные функции и процедуры глобального модуля. Это максимально приближает нас к функционалу Выполнить() из 1С 8.3.
Если вы не хотите или не можете подключать тяжелые внешние компоненты, можно воспользоваться «хитростью» со встроенной функцией Шаблон(). Эта функция предназначена для вычисления выражений внутри строк, но программисты 7.7 давно используют ее для динамического вызова кода.
Важное ограничение: функция Шаблон() умеет вызывать только функции. Попытка вызвать процедуру приведет к ошибке: «Процедура вызывается как функция».
Проанализируем, как обойти это ограничение. Нам понадобится создать в глобальном модуле специальную «функцию-обертку» (заглушку), которая будет возвращать пустое значение, но при этом выполнять нужную нам процедуру. Посмотрим на реализацию:
В Глобальном модуле прописываем:
Функция глВыполнитьЭкспортнуюПроцедуру(ИмяПроцедуры) Экспорт
// Здесь мы используем Шаблон для вызова,
// но вызываемая процедура сама должна быть функцией
Возврат Шаблон("[" + ИмяПроцедуры + "()]");
КонецФункции
Если же мы хотим вызвать именно процедуру, нам придется переписать её в глобальном модуле как функцию (добавить Возврат 1; в конце) или создать универсальный диспетчер через оператор Если, что не всегда удобно при большом количестве методов.
Однако автор темы предложил более изящный вариант: вызывать через Шаблон() одну общую функцию, которая внутри себя уже знает, что делать. Если вы планируете динамически вызывать много разных процедур, лучше всего заранее оформить их как функции, возвращающие 0 или 1.
Существует еще один «экзотический», но надежный способ, который работает вообще без внешних компонент и ограничений функции Шаблон(). Мы можем программно создать текстовый файл с расширением .ert, который будет являться внешней обработкой, и запустить его.
Рассмотрим логику процесса:
ПриОткрытии() прописан вызов нужной нам глобальной процедуры.ОткрытьФорму("Отчет", , ПутьКФайлу);.Поскольку любая внешняя обработка имеет доступ к экспортным методам глобального модуля, вызов пройдет успешно. После выполнения файл можно удалить. Этот метод медленнее остальных из-за дисковых операций, но он является самым «чистым» с точки зрения штатных механизмов платформы.
Выясним, какой метод лучше выбрать в зависимости от ситуации:
ВыполняемыйМодуль. Это самое быстрое и гибкое решение, позволяющее передавать параметры и получать результаты.Шаблон(), предварительно убедившись, что вызываемые методы являются функциями.Сервис.ВыполнитьПроцедуру() отлично подойдет для локальных вызовов, но для глобального модуля потребуются описанные выше обходные пути.Помните, что динамический вызов кода — это мощный инструмент, который требует внимательности при отладке, так как синтаксические ошибки в именах процедур будут обнаружены только в момент выполнения программы (Runtime), а не при сохранении конфигурации.