К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как выполнить процедуру на клиенте в 1С

Как выполнить процедуру на клиенте в 1С: директивы &НаКлиенте и &НаСервере, вызов серверных процедур из клиента, контекст формы, типичные ошибки и примеры кода.

В управляемых формах 1С код делится на клиентский и серверный, и платформа строго контролирует, где может выполняться каждая процедура. Чтобы процедура выполнилась на клиенте — то есть на компьютере пользователя, в контексте тонкого, толстого или веб-клиента — её нужно объявить с директивой компиляции &НаКлиенте и учитывать ограничения клиентского контекста.

Клиентский код нужен там, где требуется интерактивность: показать вопрос пользователю, открыть диалог выбора файла, запустить внешнее приложение, обработать событие элемента формы без обращения к серверу. Серверный код нужен для работы с базой данных, запросами и объектами, недоступными на клиенте. Правильное разделение — основа производительности управляемого приложения.

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

Директивы компиляции: как платформа решает, где выполняется код

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

Основные директивы:

  • &НаКлиенте — процедура выполняется на клиенте, имеет доступ к элементам формы, может показывать диалоги и работать с файловой системой пользователя;
  • &НаСервере — выполняется на сервере, имеет доступ к запросам, объектам базы данных, но не видит элементы формы напрямую;
  • &НаСервереБезКонтекста — серверная процедура без доступа к данным формы; передача параметров только через аргументы;
  • &НаКлиентеНаСервереБезКонтекста — код компилируется и там, и там; используется для простых вспомогательных функций без обращения к базе и к элементам формы.

Пример объявления клиентской процедуры:

&НаКлиенте

Процедура ПоказатьПредупреждениеПользователю()

ПоказатьПредупреждение(, "Операция выполнена на клиенте");

КонецПроцедуры

Как создать клиентскую процедуру в модуле формы

Откройте управляемую форму в конфигураторе, перейдите на вкладку «Модуль» и напишите процедуру с директивой &НаКлиенте. Самый частый сценарий — обработчик команды формы или события элемента. При создании обработчика через палитру свойств платформа сама предложит директиву, и для интерактивных действий правильный выбор — клиент.

Пример: кнопка «ОчиститьКаталог» должна очищать поле ввода без обращения к серверу. Обработчик выглядит так:

&НаКлиенте

Процедура ОчиститьКаталог(Команда)

Объект.КаталогОбмена = "";

КонецПроцедуры

Обратите внимание: данные реквизитов формы (например, Объект для формы документа) доступны и на клиенте, и на сервере — платформа синхронизирует их между сторонами. Но попытка выполнить запрос к базе или обратиться к менеджеру объекта (Документы.РеализацияТоваров) из клиентской процедуры приведёт к ошибке компиляции или выполнения.

Как добавить клиентскую процедуру
  1. 1
    Откройте форму в конфигураторе и перейдите в модуль формы
  2. 2
    Напишите процедуру с директивой &НаКлиенте
  3. 3
    Привяжите её к команде или событию элемента через палитру свойств
  4. 4
    Проверьте, что внутри нет обращений к базе данных, запросов и менеджеров объектов
  5. 5
    Запустите режим предприятия и проверьте работу в том клиенте, который используется в продуктиве

Вызов серверной процедуры из клиентской

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

&НаКлиенте

Процедура ЗаполнитьОстатки(Команда)

КоличествоСтрок = ЗаполнитьОстаткиНаСервере();

ПоказатьОповещениеПользователя("Заполнено строк: " + КоличествоСтрок);

КонецПроцедуры

&НаСервере

Функция ЗаполнитьОстаткиНаСервере()

// запрос к базе, заполнение табличной части

Возврат Объект.Товары.Количество();

КонецФункции

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

Директива &НаСервереБезКонтекста делает вызов дешевле: данные формы не передаются на сервер, но и обратиться к реквизитам формы внутри такой процедуры нельзя — всё нужное передаётся параметрами, а результат возвращается через Возврат.

Сравнение серверных вызовов

&НаСервере

Видит реквизиты и данные формы, но передаёт весь контекст на сервер — вызов дороже. Подходит для операций над данными текущей формы.

&НаСервереБезКонтекста

Не видит данные формы, параметры передаются явно. Быстрее и предпочтительнее для вычислений, не привязанных к форме.

Серверный общий модуль

Вызывается с клиента, если у модуля включён флаг «Вызов сервера». Подходит для переиспользуемой логики вне конкретной формы.

Клиентские процедуры в общих модулях

Если клиентская логика нужна в нескольких формах, её выносят в общий модуль. Поведение модуля определяется его свойствами в конфигураторе:

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

Общий модуль с одновременно включёнными флагами «Клиент» и «Сервер» компилируется в обоих контекстах — внутри него можно использовать инструкции препроцессора #Если Клиент Тогда ... #КонецЕсли, но злоупотреблять этим не стоит: код становится труднее сопровождать.

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

Асинхронные вызовы и описания оповещений

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

&НаКлиенте

Процедура ПередЗакрытиемПодтвердить(Команда)

Оповещение = Новый ОписаниеОповещения("ПослеОтветаНаВопрос", ЭтотОбъект);

ПоказатьВопрос(Оповещение, "Закрыть без сохранения?", РежимДиалогаВопрос.ДаНет);

КонецПроцедуры

&НаКлиенте

Процедура ПослеОтветаНаВопрос(Результат, ДополнительныеПараметры) Экспорт

Если Результат = КодВозвратаДиалога.Да Тогда

Закрыть();

КонецЕсли;

КонецПроцедуры

Типичная ошибка здесь — забыть слово Экспорт у процедуры-обработчика. Платформа вызывает её извне модуля по имени, поэтому без экспорта получите ошибку «Процедура или функция с указанным именем не определена» в момент срабатывания оповещения.

Типичные ошибки
01
Обращение к запросу или менеджеру объекта из &НаКлиенте — ошибка компиляции; логику с базой переносите в &НаСервере-процедуру
02
Вызов сервера в цикле по строкам таблицы — десятки сетевых обращений и зависание формы; передавайте данные одним пакетом
03
Отсутствие Экспорт у обработчика оповещения — ошибка «процедура не определена» при срабатывании
04
Использование модальных Вопрос/ОткрытьФормуМодально — код не работает в веб-клиенте и блокируется настройками конфигурации
05
Хранение промежуточных данных в переменных модуля формы на клиенте при серверных вызовах — контекст сервера не сохраняет клиентские переменные между вызовами

Ограничения клиентского контекста

На клиенте недоступны: запросы и построитель отчёта, менеджеры объектов и справочников, проведение документов, привилегированный режим, большинство прикладных серверных механизмов. Клиент работает только с данными, которые уже переданы в форму, и с ресурсами компьютера пользователя — файловой системой, внешними компонентами, COM-объектами (в толстом и тонком клиенте под Windows).

Есть и различия между клиентами. Веб-клиент не поддерживает COM и запуск внешних приложений без расширения работы с файлами; тонкий клиент требует установки расширения для работы с файлами. Поэтому код, работающий с файлами, должен проверять подключение расширения через ПодключитьРасширениеРаботыСФайлами — тоже асинхронно.

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

Как проверить, что процедура выполняется на клиенте

Самый простой способ — отладка. Поставьте точку останова в клиентской процедуре и запустите отладку: в конфигураторе в списке подключённых предметов отладки будет виден клиентский сеанс. Также можно временно добавить вывод ТипКлиентскогоПриложения через ТекущийРежимЗапуска() и информацию из ПолучитьИнформациюЭкрановКлиента() — эти функции доступны только на клиенте.

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

Контрольные точки

Как проверить результат

Компиляция модуля формы
Норма

Нет ошибок о недоступности методов в клиентском контексте

Тревожный признак

Ошибки вида «Процедура или функция не определена» или «Метод не обнаружен»

Поведение формы
Норма

Интерактивные действия выполняются мгновенно, без пауз

Тревожный признак

Каждый клик вызывает задержку — лишние серверные вызовы

Работа в веб-клиенте
Норма

Все диалоги и файловые операции работают через расширение

Тревожный признак

Ошибки модальности или недоступности COM-объектов

Частые вопросы

Можно ли вызвать клиентскую процедуру с сервера?

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

Чем &НаСервереБезКонтекста лучше &НаСервере?

Процедура без контекста не передаёт данные формы на сервер, поэтому вызов быстрее и дешевле по сети. Но обратиться к реквизитам формы внутри неё нельзя — всё передаётся параметрами. Используйте её для функций, которым нужны только входные аргументы: расчёты, обращения к справочникам, проверки.

Почему клиентская процедура не видна из другого модуля?

Процедуры модуля формы недоступны извне — форма не является глобальным контекстом. Выносите переиспользуемый код в общий модуль с флагом «Клиент (управляемое приложение)» и добавляйте Экспорт к процедурам, которые должны вызываться снаружи.

Как выполнить процедуру на клиенте по расписанию?

Через обработчик ожидания: ПодключитьОбработчикОжидания("ИмяПроцедуры", 60) в клиентском контексте. Процедура-обработчик должна быть клиентской и экспортной. Для отключения используйте ОтключитьОбработчикОжидания. Учтите, что обработчик работает только пока открыт клиентский сеанс.

Работает ли клиентский код одинаково в тонком и веб-клиенте?

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

Итог

Что важно запомнить

Клиентская процедура объявляется с директивой &НаКлиенте в модуле формы или размещается в общем модуле с флагом «Клиент». Работа с базой данных возможна только через вызов серверных процедур, причём вызовы следует минимизировать и не выполнять в циклах. Асинхронные операции оформляются через описания оповещений с экспортными обработчиками, а критичные проверки всегда дублируются на сервере.