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

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

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

В этом материале мы подробнее проанализируем причины такого поведения платформы 1С и разберем практические способы, которые позволят сохранить всю необходимую логику внутри одного файла обработки .epf.

Выясним причину ошибки компиляции модуля формы

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

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

Рассмотрим несколько проверенных подходов к решению этой проблемы.

Способ 1. Проверка существования модуля и метод Вычислить()

Разберем вариант, когда алгоритм должен обращаться к специфическому общему модулю конкретной конфигурации. Чтобы статическая проверка синтаксиса не прерывала работу, исключим прямое упоминание имени модуля из кода. Для этого сначала проверим наличие модуля в дереве метаданных, после чего выполним динамический вызов через функцию Вычислить().

Посмотрим на пример реализации данного подхода:


ИмяМодуля = "РаботаСНоменклатуройПереопределяемый";

Если Метаданные.ОбщиеМодули.Найти(ИмяМодуля) <> Неопределено Тогда
    ОбщийМодуль = Вычислить(ИмяМодуля);
    ОбщийМодуль.ЗаполнитьСпецифичныеДанные(ТаблицаЗначений);
КонецЕсли;

В данном случае транслятор синтаксиса не видит прямого обращения к модулю РаботаСНоменклатуройПереопределяемый, так как имя передано в виде текстовой строки. Если модуль присутствует в конфигурации, метод Вычислить() вернет ссылку на него, и обработка безошибочно выполнит нужный алгоритм.

Способ 2. Динамическое выполнение кода с помощью Выполнить() и текстовых макетов

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

Разберем по шагам порядок действий:

  1. Добавим в обработку макет с типом Текстовый документ и назовем его, например, АлгоритмДляБазы1.
  2. Поместим текст процедуры 1С прямо в этот макет.
  3. В модуле формы прочитаем текст макета и передадим его в оператор Выполнить().

Проанализируем пример программы:


Макет = ПолучитьМакет("АлгоритмДляБазы1");
ТекстКода = Макет.ПолучитьТекст();

Попытка
    Выполнить(ТекстКода);
Исключение
    Сообщить("Не удалось выполнить алгоритм: " + ОписаниеОшибки());
КонецПопытки;

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

Способ 3. Отказ от типовых процедур и использование автономного кода

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

Для выполнения стандартных задач на обычных формах опирайтесь на универсальные механизмы платформы 1С:

Способ 4. Использование процедур-заглушек и условий препроцессора

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

Рассмотрим пример такого кода:


#Если Ложь Тогда
Процедура ГлобальнаяПроцедураИзДругойБазы()
    // Заглушка для прохождения синтаксического контроля
КонецПроцедуры
#КонецЕсли

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

Способ 5. Разделение бизнес-логики по отдельным формам обработки

Платформа 1С компилирует код модуля формы только в момент её непосредственного вызова. Это дает возможность разместить в рамках одного файла .epf сразу несколько форм:

  1. Стартовая (главная) форма: содержит общую логику, определяет тип текущей конфигурации или дает пользователю выбор нужного режима.
  2. Форма для Конфигурации А: содержит код и кнопки, предназначенные только для первой базы.
  3. Форма для Конфигурации Б: содержит узкоспециализированный код для второй базы.

При запуске стартовая форма открывает нужную подчиненную форму методом ОткрытьФорму(). Форма для параллельной конфигурации при этом не открывается и, следовательно, её модуль платформой не компилируется.

← На главную