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