Рассказывает моя коллега Александра, разработчик 1С в нашей компании.
В среде 1С начинающие разработчики часто путают директивы компиляции и инструкции препроцессора. Да, эти конструкции являются инструментами для управления тем, какой код и в каком месте будет исполняться. Но несмотря на схожие задачи, они работают на разных этапах и имеют разный синтаксис.
Директивы компиляции определяют, в каком контексте (на стороне клиента или сервера) будет скомпилирована и выполнена конкретная процедура или функция. Пишутся перед объявлением метода и начинаются с символа &.
Если директива не указана, по умолчанию применяется &НаСервере.
Основные директивы компиляции:
- &НаКлиенте – указывает, что процедура или функция выполняется в клиентском контексте. Доступны только данные формы и клиентские объекты.
Что можно: открывать окна, задавать вопросы пользователю, работать с файлами на локальном диске, открыть форму.
Что нельзя: обращаться к базе данных напрямую (запросы, чтение объектов).
&НаКлиенте
Процедура НазваниеПроцедуры()
//Код выполняемый в клиентском контексте
КонецПроцедуры

- &НаСервере - код выполняется на сервере. Имеет полный доступ к базе данных и контексту формы.
Что можно: выполнять тяжелые запросы, изменять данные в БД, проводить документы.
Что нельзя: выводить предупреждения, открывать формы или обращаться к файловой системе пользователя.
&НаСервере
Процедура НазваниеПроцедуры()
//Код выполняемый на сервере
КонецПроцедуры

- &НаСервереБезКонтекста – выполняется на сервере, но без доступа к контексту формы (реквизитам, элементам управления). Используется для получения статических данных или выполнения вычислений, не зависящих от формы. Повышает производительность за счёт минимизации трафика между клиентом и сервером.
& НаСервереБезКонтекста
Процедура НазваниеПроцедуры(ПередаваемыйПараметр)
//Код выполняемый на сервере
КонецПроцедуры

- &НаКлиентеНаСервереБезКонтекста – редкая директива для универсальных алгоритмов (например, простая математика или проверка формата строки), которые должны работать везде без обращения к данным формы.
& НаСервереБезКонтекста
Процедура НазваниеПроцедуры(ПередаваемыйПараметр)
//Код выполняемый и на клиенте и на сервере
КонецПроцедуры

Инструкции препроцессора – управляют «сборкой» исходного текста модуля еще до начала компиляции. Они позволяют включать или исключать целые блоки кода в зависимости от условий среды. Начинаются с символа #.

Основные инструкции препроцессора:
- #Если ... #ИначеЕсли ... #КонецЕсли - условная компиляция в зависимости от окружения, позволяет исключить части кода, которые недоступны в определенном контексте.
#Если ВебКлиент Тогда
// код для вебR09;клиента
#Иначе
// другой код
#КонецЕсли

- #Область и #КонецОбласти - не влияют на логику работы. Их задача — «порядок» в коде. Они позволяют сворачивать логические блоки (например «ОбработчикиСобытий», «СлужебныеПроцедурыИФункци»).
#Область НазваниеОбласти
// код
#КонецОбласти

- #Вставка и #КонецВставки/ #Удаление и #КонецУдаления – используется в расширениях конфигурации для модификации кода в процедурах с аннотацией &ИзменениеИКонтроль: добавляет или удаляет часть кода.
&ИзменениеИКонтроль
#Удаление
// старый код
#КонецУдаления
#Вставка
// новый код
#КонецВставки
|
Характеристика |
Директивы компиляции (&) |
Инструкции препроцессора (#) |
|
Уровень |
Применяются к конкретному методу (процедуре/функции). |
Могут применяться к любому фрагменту кода, переменным или методам. |
|
Модули |
В основном используются в модулях управляемых форм и команд. |
Используются во всех типах модулей (общие, модули объекта, менеджера и т.д.). |
|
Смысл |
Указывают платформе, куда отправить выполнение метода. |
Буквально удаляют ненужный код из текста перед компиляцией. |
Возможные ошибки при использовании Инструкций препроцессора в модуле менеджера
В модулях объектов и менеджеров контекст определяется платформой автоматически. В 99% случаев в современном управляемом приложении модуль менеджера исполняется на сервере. Однако для обеспечения универсальности и корректной работы в «толстом клиенте» используются инструкции препроцессора. Они физически вырезают куски кода из компиляции в определенных режимах.
В этом режиме платформа может пытаться скомпилировать модуль менеджера на клиенте, даже если он не предназначен для клиентского выполнения. Это приводит к ошибкам, потому что:
• на клиенте недоступны многие объекты и методы, работающие с базой данных;
• код может содержать вызовы, которые имеют смысл только на сервере.
Модуль менеджера компилируется на клиенте в следующих случаях:
• объект явно создаётся и вызывается в клиентском коде,
• платформа неявно обращается к модулю менеджера для вызова обработчиков событий на клиенте,
• при проверке конфигурации в режиме «Толстый клиент, управляемое приложение» система анализирует возможность компиляции модулей на клиенте.
Ошибка «Пустого метода» (Метод не обнаружен)
Самая частая ошибка: обернуть процедуру в условие предпроцессора, а затем попытаться вызвать её из другого контекста.
Создадим на форме документа «Реализация товаров и услуг» команду, и в обработчике На Сервере вызовем в ней процедуру из модуля менеджера с условием «#Если ТолстыйКлиентУправляемоеПриложение Тогда …..#КонецЕсли».
Модуль формы:

Модуль Менеджера:

При попытке выполнить команду в режиме предприятия, мы получим Ошибку:

Почему это происходит: Для вызова с сервера код внутри «#Если ТолстыйКлиентУправляемоеПриложение» просто не существует. Платформа не видит экспортируемую процедуру.
Как правильно: Добавить условие предпроцессора «#Если Сервер»
![]()
Синтаксический «Разрыв» процедуры
Ошибка возникает, когда открывающая часть процедуры попадает в блок препроцессора, а закрывающая — нет (или наоборот).
#Если Сервер Тогда
Процедура РассчитатьОстатокТест(МассивТоваров) Экспорт
#КонецЕсли
////текст процедуры
КонецПроцедуры

В данном случае синтаксический контроль в конфигураторе не выдаст ошибок. Если это скомпилируется на клиенте (например, в толстом клиенте), препроцессор увидит «КонецПроцедуры» без начала и выдаст критическую ошибку синтаксиса.
Отсутствие кода в одной из ветвей компиляции
Не стоит объявлять переменные внутри предпроцессоров. Всегда инициализируйте переменные либо в обеих ветках препроцессора, либо до их начала.
Процедура РассчитатьОстатокТест(МассивТоваров) Экспорт
#Если Сервер Тогда
МассивСообщений = Новый Массив;
#КонецЕсли
МассивСообщений.Добавить("Тест процедуры"); // Ошибка на клиенте: Переменная 'МассивСообщений' не определена
КонецПроцедуры

Инструкции препроцессора — мощный инструмент для адаптации кода 1С под разные условия выполнения. Однако их неправильное использование может привести к трудноуловимым ошибкам и усложнить поддержку конфигурации. Поэтому всегда тестируйте код в разных режимах. Проверяйте конфигурацию в разных окружениях (клиент, сервер, вебR09;клиент и т. д.), чтобы убедиться, что все ветки кода корректно компилируются и выполняются.
Вступайте в нашу телеграмм-группу Инфостарт