Процедуры во встроенном языке 1С 8.3: объявление, параметры, вызов
Содержание
Чтобы добавить процедуру в 1С, откройте нужный модуль в Конфигураторе и напишите блок Процедура ИмяПроцедуры() ... КонецПроцедуры. Если её будут вызывать из другого модуля, допишите после скобок Экспорт, а в модуле формы поставьте над ней директиву &НаКлиенте или &НаСервере.
Дальше всё упирается в детали: где именно писать код, как передавать параметры, почему процедура «не видна» из формы и чем она отличается от функции. Ниже разобраны все эти вопросы на примерах для платформы 8.3 и управляемых форм.
Где добавить процедуру: выбор модуля в Конфигураторе
Сначала решите, в каком модуле будет жить код. От этого зависит, откуда процедуру можно вызвать и где она выполнится — на клиенте или на сервере.
| Модуль | Как открыть | Для чего |
|---|---|---|
| Модуль формы | Открыть форму → вкладка Модуль внизу редактора | Обработчики кнопок, полей, событий формы |
| Модуль объекта | Правый клик по справочнику или документу → Открыть модуль объекта | Логика одного элемента: проверки, заполнение, ПередЗаписью |
| Модуль менеджера | Правый клик → Открыть модуль менеджера | Действия над всем справочником: поиск, печать, служебные выборки |
| Общий модуль | Ветка Общие → Общие модули → Добавить | Код, который нужен в разных местах конфигурации |
| Модуль приложения | Правый клик по корню конфигурации → Открыть модуль управляемого приложения | События запуска и завершения программы |
Пошагово: новая процедура в общем модуле
- Откройте базу в режиме Конфигуратор и выберите
Конфигурация → Открыть конфигурацию. - В дереве раскройте
Общие → Общие модули, нажмитеДобавить. - Задайте имя, например
РаботаСТоварами, и отметьте флаги исполнения:Сервер,Клиент (управляемое приложение), при необходимостиВызов сервера. - Двойным щелчком откройте модуль и напишите процедуру.
- Сохраните конфигурацию и обновите конфигурацию базы данных (
F7).
Обработчик события формы — без ручного набора
Для кнопок и событий формы процедуру удобнее создавать не руками, а через палитру свойств:
- Выделите элемент формы или команду и откройте свойства (
Alt+Enter). - Перейдите в группу
Событияи нажмите кнопку с лупой напротив нужного события. - Для команды платформа спросит, как создать обработчик: только на клиенте, на клиенте и процедура на сервере, на клиенте и процедура на сервере без контекста.
Платформа сама впишет директиву, имя и параметры, а в свойстве события появится ссылка на процедуру. Если написать обработчик вручную и не привязать его в свойствах, он не сработает.
Если модуль большой, раскладывайте процедуры по областям #Область ИмяОбласти ... #КонецОбласти. В типовых конфигурациях приняты области ПрограммныйИнтерфейс, СлужебныйПрограммныйИнтерфейс и СлужебныеПроцедурыИФункции — по ним сразу видно, что можно вызывать снаружи.
Синтаксис объявления процедуры в модуле 1С
Общий вид объявления:
&НаСервере
Процедура ИмяПроцедуры(Параметр1, Знач Параметр2, Параметр3 = 0) Экспорт
Перем ЛокальнаяПеременная;
// операторы
КонецПроцедуры
Что здесь обязательно, а что нет:
- 🔹
ПроцедураиКонецПроцедуры— обязательны. Английский вариант:Procedure ... EndProcedure. - 🔹 Имя — обязательно. Начинается с буквы или подчёркивания, без пробелов. Принято писать слитно с заглавных:
ЗаполнитьТабличнуюЧасть. - 🔹 Скобки — обязательны, даже если параметров нет:
Процедура Обновить(). - 🔹
Экспорт— по желанию, открывает процедуру для других модулей. - 🔹 Директива компиляции — нужна в модулях форм и команд, в модуле объекта не используется.
- 🔹
Перемвнутри процедуры — по желанию. Локальная переменная создаётся и простым присваиваниемСумма = 0;.
Порядок разделов модуля
У модуля жёсткая структура. Нарушите её — получите ошибку компиляции:
- Раздел объявления переменных модуля (
Перем ... ;). - Раздел процедур и функций.
- Раздел основной программы — операторы вне процедур, выполняются при создании модуля.
Внутри второго раздела порядок свободный: процедуру можно вызвать в тексте выше, чем она объявлена.
Досрочный выход
Оператор Возврат; прерывает процедуру в любом месте. Значение после него в процедуре писать нельзя.
Процедура ПроверитьКонтрагента(Контрагент)
Если НЕ ЗначениеЗаполнено(Контрагент) Тогда
Сообщить("Не указан контрагент");
Возврат;
КонецЕсли;
// основная проверка
КонецПроцедуры
Параметры процедуры: по ссылке, Знач и значения по умолчанию
По умолчанию в 1С параметр передаётся по ссылке. Процедура работает с той же переменной, что и вызывающий код. Изменили параметр внутри — изменилась переменная снаружи.
Процедура Удвоить(Число)
Число = Число * 2;
КонецПроцедуры
А = 5;
Удвоить(А);
// А = 10
Ключевое слово Знач перед параметром включает передачу по значению: процедура получает копию.
Процедура Удвоить(Знач Число)
Число = Число * 2;
КонецПроцедуры
А = 5;
Удвоить(А);
// А = 5, исходная переменная не изменилась
Ловушка со Знач и коллекциями
Для структур, массивов, таблиц значений и объектов Знач копирует ссылку, а не сам объект. Присвоить параметру новый массив без последствий можно. А вот добавленный элемент увидит и вызывающий код.
Процедура Дополнить(Знач Список)
Список.Добавить("новый"); // изменит исходный массив
Список = Новый Массив; // исходный массив не тронет
КонецПроцедуры
Необязательные параметры
Параметру можно задать значение по умолчанию. Тогда при вызове его разрешено пропустить:
Процедура ЗаписатьВЖурнал(Текст, Уровень = "Информация", Важно = Ложь)
// ...
КонецПроцедуры
ЗаписатьВЖурнал("Старт обмена");
ЗаписатьВЖурнал("Ошибка", , Истина); // второй параметр пропущен
Значение по умолчанию — только литерал: число, строка, дата, Истина, Ложь, Неопределено, Null. Вызов функции или Новый Структура там не допускаются. Если нужна пустая структура по умолчанию, ставьте Неопределено и создавайте её внутри.
Сколько параметров — нормально
Если параметров больше пяти-шести, их удобнее передавать одной структурой Параметры. Так проще добавлять новые поля, не трогая все места вызова.
Область видимости процедуры: Экспорт и директивы компиляции
Видимость процедуры задают три вещи: Экспорт, директива компиляции и флаги общего модуля.
Экспорт
Без Экспорт процедура видна только внутри своего модуля. С ним — из других модулей через объект или имя модуля:
| Где объявлена | Как вызвать снаружи |
|---|---|
Общий модуль РаботаСТоварами | РаботаСТоварами.ПересчитатьЦены(Документ); |
| Модуль менеджера справочника | Справочники.Номенклатура.ЗагрузитьИзФайла(Путь); |
| Модуль объекта документа | ДокументОбъект.ЗаполнитьПоОснованию(Основание); |
| Глобальный общий модуль | ПересчитатьЦены(Документ); — без имени модуля |
Директивы компиляции в модуле формы
| Директива | Где выполняется | Доступ к данным формы |
|---|---|---|
&НаКлиенте | На клиенте | Да |
&НаСервере | На сервере | Да, форма передаётся на сервер |
&НаСервереБезКонтекста | На сервере | Нет, только параметры |
&НаКлиентеНаСервереБезКонтекста | Там, откуда вызвали | Нет |
Процедура без директивы в модуле формы считается &НаСервере. Пишите директиву явно — так код читают без догадок.
&НаСервереБезКонтекста работает быстрее &НаСервере: платформа не гоняет данные формы на сервер и обратно. Если серверной процедуре нужны два-три значения, передайте их параметрами.
Флаги общего модуля
- 🖥️
Сервер— код компилируется на сервере. - 💻
Клиент (управляемое приложение)— доступен на клиенте. - 🔄
Вызов сервера— экспортные процедуры серверного модуля можно вызвать с клиента. - 🌐
Глобальный— процедуры вызываются без имени модуля. Злоупотреблять не стоит: такие модули компилируются при старте программы. - 🔐
Привилегированный— код выполняется без проверки прав. Включайте точечно.
Как вызвать процедуру из формы, модуля объекта и с клиента
Вызов — это имя, скобки и аргументы через запятую:
ПересчитатьИтоги();
РаботаСТоварами.ПересчитатьЦены(Объект.Ссылка, Истина);
С клиента на сервер в форме
Типичная связка: кнопка срабатывает на клиенте, тяжёлая работа уходит на сервер.
&НаКлиенте
Процедура Заполнить(Команда)
ЗаполнитьНаСервере();
Элементы.Товары.Обновить();
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьНаСервере()
ДокументОбъект = РеквизитФормыВЗначение("Объект");
ДокументОбъект.ЗаполнитьТовары();
ЗначениеВРеквизитФормы(ДокументОбъект, "Объект");
КонецПроцедуры
Здесь ЗаполнитьТовары — экспортная процедура модуля объекта. Из серверной процедуры формы она доступна после получения объекта.
Вызов из модуля объекта или менеджера
С клиента напрямую вызвать процедуру модуля объекта нельзя. Сначала перейдите на сервер — через &НаСервере в форме или через общий модуль с флагом Вызов сервера.
Отложенный вызов по имени
Иногда процедуру вызывают не напрямую:
- ⏱️
ПодключитьОбработчикОжидания("ОбновитьСтатус", 5)— клиентская процедура формы запустится через 5 секунд. Третий параметрИстинаделает вызов однократным. - 📨
Новый ОписаниеОповещения("ПослеВопроса", ЭтотОбъект)— процедураПослеВопросасработает, когда пользователь ответит вПоказатьВопрос. Обработчик должен быть экспортным.
Асинхронные процедуры
В платформе 8.3.18 и выше появились Асинх и Ждать. Процедура с модификатором Асинх может дождаться ответа пользователя прямо в теле:
&НаКлиенте
Асинх Процедура Удалить(Команда)
Ответ = Ждать ВопросАсинх("Удалить строку?", РежимДиалогаВопрос.ДаНет);
Если Ответ = КодВозвратаДиалога.Да Тогда
// удаление
КонецЕсли;
КонецПроцедуры
Процедура или функция: в чём разница
Разница одна по сути: функция возвращает значение, процедура — нет.
| Признак | Процедура | Функция |
|---|---|---|
| Ключевые слова | Процедура ... КонецПроцедуры | Функция ... КонецФункции |
| Возврат значения | Нет, только Возврат; | Возврат Значение; |
| Использование в выражении | Нельзя | Итог = Сумма(А, Б); |
| Вызов как оператор | Да | Да, результат отбрасывается |
| Обработчики событий | Почти всегда процедуры | Редко |
Когда что выбирать:
- ✅ Процедура — действие: записать, заполнить, пересчитать, показать.
- ✅ Функция — вопрос: получить, найти, проверить, вычислить.
Хорошее правило — имя подсказывает тип. ЗаполнитьТовары — процедура, ПолучитьОстаток — функция. Если процедура должна вернуть несколько результатов, передайте параметр по ссылке или сделайте функцию, возвращающую структуру. Второй вариант читается проще.
Ошибки при создании процедур и как их исправить
Экспорт, имя общего модуля перед точкой и флаги исполнения: клиентский код не видит процедуру серверного модуля без флага «Вызов сервера».Ещё несколько промахов, которые не дают текста ошибки, но ломают логику:
- ⚠️ Обработчик не привязан к событию. Процедура есть, но в свойствах элемента формы поле события пустое. Код просто не запускается.
- ⚠️ Серверный вызов в цикле.
&НаСерверевнутри клиентского цикла на 500 строк — это 500 обращений к серверу. Соберите данные и вызовите сервер один раз. - ⚠️ Параметр по ссылке меняется случайно. Процедура «подчищает» входную строку, а вызывающий код потом работает с изменённым значением. Защищайтесь через
Знач. - ⚠️ Правка типовой конфигурации напрямую. Новую процедуру в типовую базу лучше добавить в расширение: при обновлении она не потеряется. Расширения доступны с платформы 8.3.6.
Изменения в модулях общих объектов требуют обновления конфигурации базы данных. Делайте его в нерабочее время и после резервной копии, если рядом меняется структура метаданных.
Частые вопросы
Можно ли вызвать процедуру внутри самой себя?
Как сделать необязательный параметр в середине списка?
Процедура1(А, , В).Зачем писать Знач, если параметр и так не меняется?
Как процедуре вернуть результат, если это не функция?
Можно ли объявить переменную модуля и использовать её во всех процедурах?
Перем ИмяПеременной; в начале модуля. С Экспорт она будет доступна и снаружи, например через объект формы.