Вызов функции во встроенном языке 1С 8.3: от синтаксиса до фоновых заданий

· 10 мин

Содержание

Чтобы запустить функцию в 1С 8.3, её нужно вызвать по имени и забрать результат в переменную: Итог = МояФункция(Параметр1, Параметр2);. Процедуру вызывают так же, но без присваивания — отдельной строкой МояПроцедура();. Функция обязана вернуть значение через оператор Возврат, процедура ничего не возвращает. Если метод объявлен с ключевым словом Экспорт, его видно за пределами своего модуля.

Разовый прогон одной функции делают прямо в отладчике Конфигуратора через окно Отладка → Вычислить выражение, а в рабочей базе вызов встраивают в команду формы, обработчик события или фоновое задание. Ниже — все способы вызова, передача параметров, контекст клиент/сервер и разбор ошибок, которые чаще всего мешают коду запуститься.

Синтаксис вызова процедур и функций

Разница между процедурой и функцией в 1С одна: функция возвращает значение, процедура — нет.

// Объявление
Функция СуммаСНДС(Сумма, Ставка = 20) Экспорт
    Возврат Сумма + Сумма * Ставка / 100;
КонецФункции

Процедура ЗаписатьВЖурнал(Текст) Экспорт
    ЗаписьЖурналаРегистрации("МояПодсистема", , , , Текст);
КонецПроцедуры

Вызов выглядит так:

Цена = СуммаСНДС(1000);       // 1200, ставка по умолчанию
Цена = СуммаСНДС(1000, 10);   // 1100
ЗаписатьВЖурнал("Расчёт выполнен");

Ключевые правила запуска:

  • 🔹 Результат функции нужно куда-то деть. Присвойте его переменной, передайте в другую функцию или в условие. Можно вызвать функцию и как процедуру, отдельной строкой — тогда результат просто отбрасывается.
  • 🔹 Процедуру нельзя вызвать как функцию. Строка Х = МояПроцедура(); вызывает ошибку Обращение к процедуре как к функции.
  • 🔹 Скобки обязательны даже без параметров. ОбновитьДанные() — вызов, ОбновитьДанные без скобок вызовом не является.
  • 🔹 Регистр и язык. Встроенный язык 1С понимает и русский, и английский синтаксис (Функция/Function, Возврат/Return), регистр в именах не важен.

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

Где виден метод: модули, экспорт и контекст выполнения

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

Где объявлена функцияКак вызвать из другого местаУсловие
Общий модульОбщийМодуль.Метод()Метод с Экспорт, модуль не глобальный
Глобальный общий модульпросто Метод()Флаг «Глобальный» у модуля
Модуль объекта (документа, справочника)Объект.Метод()Экспорт, есть ссылка на объект
Модуль менеджераДокументы.Реализация.Метод()Экспорт в модуле менеджера
Модуль формывнутри самой формы — по имениза пределами формы напрямую не вызвать

Общие модули — главный инструмент для кода, который нужен в разных местах. У модуля есть флаги Клиент (управляемое приложение), Сервер, Вызов сервера, Глобальный. Они задают, откуда метод доступен. Серверный метод клиент напрямую не вызовет: нужен либо флаг «Вызов сервера», либо серверный контекст формы.

Вот как выглядит вызов из разных мест на практике:

// Метод общего модуля (обычный, не глобальный)
Итог = РасчётыСервер.СуммаДокумента(СсылкаНаДокумент);

// Метод глобального общего модуля — без префикса модуля
ЗаписатьСобытие("Старт обработки");

// Метод менеджера документа
НомерНовый = Документы.РеализацияТоваровУслуг.ПолучитьСледующийНомер();

// Метод модуля объекта — через ссылку на объект
Объект = СсылкаНаДокумент.ПолучитьОбъект();
Объект.ПересчитатьСтроки();

Если имя общего модуля или метода указано неверно, платформа сообщит об этом ещё на этапе синтаксического контроля (Текстовое меню → Синтаксический контроль или Ctrl+F7). Запускать базу ради проверки опечатки не нужно.

Директивы компиляции на клиенте и сервере

В модуле формы перед каждым методом ставят директиву — где он исполняется:

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

Типовая схема: клиентский обработчик нажатия кнопки вызывает серверный метод формы, тот считает и возвращает результат.

&НаКлиенте
Процедура РассчитатьНажатие(Команда)
    ЗаполнитьИтогНаСервере();   // прыжок клиент → сервер
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьИтогНаСервере()
    Объект.Итог = ПодсчётДанных();  // доступ к базе — только здесь
КонецПроцедуры

Каждый вызов &НаСервере из клиента — это обращение к серверу по сети. В цикле такие вызовы резко тормозят форму. Собирайте данные за один серверный вызов, а не по одному в цикле.

Передача параметров и возврат значения

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

Процедура Удвоить(Знач Входное, Результат)
    Входное = Входное * 2;   // снаружи не изменится — передано по значению
    Результат = Входное;     // изменится — передано по ссылке
КонецПроцедуры

Что полезно знать о параметрах:

  • 🔸 Значения по умолчанию задаются только для простых типов: Функция Расчёт(Сумма, Ставка = 20). Необязательные параметры идут в конце списка.
  • 🔸 Пропустить параметр в середине можно запятой: Метод(Знач1, , Знач3) — второй возьмёт значение по умолчанию.
  • 🔸 Вернуть несколько значений можно двумя путями: завести выходные параметры (по ссылке) либо вернуть структуру через Возврат Новый Структура("Сумма, Налог", С, Н). Второй вариант читается чище.
  • 🔸 Ранний выход. Возврат Значение; в функции и Возврат; в процедуре прерывают выполнение и передают управление обратно вызвавшему коду.

Распространённая ошибка — ждать, что по значению передастся таблица значений или структура. Объектные типы передаются ссылкой на один и тот же объект, и Знач копирует только саму ссылку, а не содержимое. Чтобы получить независимую копию, используйте метод Скопировать() у таблицы значений или рекурсивное копирование структуры.

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

Асинхронный вызов и запуск в фоне

Если функция долго считает, запускать её в основном потоке нельзя — форма «зависнет». В 1С 8.3 есть два механизма: асинхронные вызовы на клиенте и фоновые задания на сервере.

Асинхронные методы на клиенте. Диалоги (выбор файла, вопрос пользователю) в тонком и веб-клиенте работают только асинхронно. Начиная с платформы 8.3.18 доступен современный синтаксис Асинх/Ждать:

&НаКлиенте
Асинх Процедура СпроситьИЗаписать()
    Ответ = Ждать ВопросАсинх("Записать документ?", РежимДиалогаВопрос.ДаНет);
    Если Ответ = КодВозвратаДиалога.Да Тогда
        ЗаписатьНаСервере();
    КонецЕсли;
КонецПроцедуры

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

Фоновые задания на сервере. Чтобы запустить функцию в отдельном потоке на сервере, применяют объект ФоновыеЗадания. Метод должен быть экспортной процедурой серверного общего модуля:

&НаСервереБезКонтекста
Функция ЗапуститьФон()
    Параметры = Новый Массив;
    Параметры.Добавить(ТекущаяДата());
    Задание = ФоновыеЗадания.Выполнить("РасчётыСервер.ПересчитатьОстатки", Параметры);
    Возврат Задание.УникальныйИдентификатор;
КонецФункции

В типовых конфигурациях на Библиотеке стандартных подсистем для долгих операций есть готовый общий модуль ДлительныеОперации с методами ВыполнитьФункцию и ВыполнитьПроцедуру. Он сам создаёт фоновое задание и показывает пользователю индикатор прогресса — писать обвязку вручную не нужно.

Фоновое задание выполняется от имени своего сеанса и не видит данных формы. Передавайте в него только сериализуемые значения (ссылки, примитивы, структуры из них), а результат возвращайте через регистр, временное хранилище или сам объект задания.

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

Иногда нужно просто прогнать метод и посмотреть результат, не встраивая вызов в интерфейс. Способы по возрастанию трудозатрат:

  1. Окно «Вычислить выражение». В режиме отладки встаньте на точку останова, откройте Отладка → Вычислить выражение (или выделите вызов и нажмите Shift+F9), впишите МояФункция(123) и нажмите «Рассчитать». Результат виден сразу.
  2. Табло. Добавьте выражение в Табло (Отладка → Табло) — оно будет пересчитываться на каждом шаге.
  3. Временная команда. В обработке или форме заведите кнопку с одной строкой вызова. Самый наглядный способ для метода, которому нужен контекст формы.
  4. Внешняя обработка. Для разовой проверки серверного кода соберите внешнюю обработку с модулем объекта и запустите её через Файл → Открыть.
Перед запуском функции проверьте
Выполнено: 0 / 5

Отладка и разбор ошибок при вызове

Отладчик 1С встроен в Конфигуратор. Чтобы он заработал, в настройках информационной базы должна быть включена отладка, а запуск вести из Конфигуратора командой Отладка → Начать отладку (F5) либо подключиться к уже запущенному сеансу через Отладка → Подключение.

Базовые приёмы:

  • 🔺 Точка останова — F9 на строке. Выполнение встанет здесь, и можно посмотреть значения переменных.
  • 🔺 Шаги — F11 заходит внутрь вызываемой функции, F10 выполняет её целиком не заходя, Shift+F11 выходит из текущего метода.
  • 🔺 Стек вызовов показывает, какая функция кого вызвала — помогает понять, откуда пришли «неправильные» параметры.
  • 🔺 Отладка на сервере требует, чтобы отладка по протоколу была разрешена в настройках кластера; иначе серверные &НаСервере-методы под отладчик не попадут.

Частые ошибки, из-за которых функция не запускается:

Диагностика: выберите симптом

Оптимизация и хорошие привычки при вызове

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

  • ⚡ Минимум серверных вызовов. Один «толстый» вызов &НаСервере дешевле десяти мелких. Собирайте нужные данные за одно обращение.
  • ⚡ Без контекста, где можно. &НаСервереБезКонтекста не гоняет данные формы туда-обратно — используйте его для чистых расчётов.
  • ⚡ Функции без побочных эффектов. Функция, которая только считает и возвращает результат, предсказуема и легко тестируется. Запись в базу выносите в процедуры.
  • ⚡ Понятные имена. РассчитатьНДСПоСтавке вместо Расчёт2. Через полгода читать код будете вы же.
  • ⚡ Проверка входных данных. В начале метода проверьте параметры на Неопределено и пустые ссылки — это дешевле, чем ловить ошибку в середине расчёта.
Проверьте себя
Как вызвать функцию, чтобы получить её результат?
Какая директива выполняет код на сервере без передачи данных формы?
Что делает ключевое слово Знач перед параметром?

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

Можно ли вызвать функцию формы из общего модуля?
Напрямую — нет. Методы модуля формы живут внутри формы. Вынесите нужную логику в общий модуль и вызывайте её и из формы, и из другого кода, либо передайте в общий модуль уже готовые данные.
Почему клиентский код не видит мою серверную функцию?
Клиент и сервер — разные контексты. Чтобы серверный метод общего модуля был доступен с клиента, у модуля должен стоять флаг «Вызов сервера», а сам метод — быть экспортным. Методы формы вызываются через серверный метод этой же формы.
В чём разница между `Выполнить` и `Вычислить`?
Вычислить("Выражение") возвращает результат выражения, его можно присвоить. Выполнить("Оператор") исполняет оператор и ничего не возвращает. Оба работают со строкой кода и на сервере ограничены безопасным режимом.
Как передать несколько значений обратно из функции?
Либо через параметры по ссылке (без Знач), либо вернуть структуру: Возврат Новый Структура("Сумма, Налог", С, Н). Структура нагляднее и не путает порядок выходных параметров.
Нужно ли фоновое задание, если функция считает пару секунд?
Нет. Фоновые задания оправданы для длительных операций — пересчёта остатков, массовой обработки документов, выгрузок. Для быстрых расчётов хватит обычного серверного вызова.