Разработка и Конфигурация · 11 мин
Как писать процедуры в 1С
Как писать процедуры в 1С: синтаксис объявления, параметры, директивы компиляции, экспортные процедуры, примеры кода и разбор типичных ошибок разработчиков.
Процедура — основной строительный блок кода на встроенном языке 1С. В неё помещают логику, которую нужно выполнить многократно: расчёт суммы документа, проверку заполнения реквизитов, формирование движений по регистрам. Грамотно написанная процедура имеет понятное имя, принимает параметры и не зависит от лишнего контекста — это упрощает поддержку конфигурации и снижает количество ошибок при доработках.
Процедуры пишутся в модулях: модуле формы, модуле объекта, общем модуле, модуле менеджера. От места размещения зависит, где процедура будет доступна и на каком контексте (клиент или сервер) она выполнится. Прежде чем писать код, стоит решить, какой модуль подходит под задачу — это определяет директивы компиляции и видимость процедуры из других частей конфигурации.
Ниже разобран синтаксис объявления, работа с параметрами, отличия процедур от функций, директивы компиляции, экспортные процедуры и типичные ошибки начинающих разработчиков.
Синтаксис объявления процедуры
Минимальная процедура состоит из ключевого слова Процедура, имени, круглых скобок с параметрами, тела и слова КонецПроцедуры. Имена пишутся по-русски или по-английски, без пробелов; принятый стиль — «верблюжья нотация»: РассчитатьСуммуДокумента.
Процедура РассчитатьСуммуДокумента(ТабличнаяЧасть)
Итог = 0;
Для Каждого Строка Из ТабличнаяЧасть Цикл
Итог = Итог + Строка.Количество * Строка.Цена;
КонецЦикла;
Сообщить("Итоговая сумма: " + Итог);
КонецПроцедуры
Вызов процедуры выполняется по имени с передачей аргументов: РассчитатьСуммуДокумента(Объект.Товары);. Точка с запятой в конце оператора обязательна. Если параметров нет, скобки всё равно пишутся — пустые.
Тело процедуры может содержать любые операторы встроенного языка: присваивания, условия Если...Тогда...КонецЕсли, циклы, вызовы других процедур и функций, обращения к объектам конфигурации. Досрочный выход выполняется оператором Возврат;.
Параметры: значение, знач и значения по умолчанию
Параметры перечисляются в скобках через запятую. По умолчанию параметр передаётся по ссылке: изменения внутри процедуры затронут переданную переменную. Если такое поведение нежелательно, перед именем параметра ставится ключевое слово Знач — тогда внутрь попадает копия значения.
Процедура УвеличитьЦену(Цена, Знач Процент) Экспорт
Цена = Цена * (1 + Процент / 100); // изменится и у вызывающего кода
КонецПроцедуры
Параметру можно задать значение по умолчанию: Процедура Печатать(Документ, КоличествоКопий = 1). Такие параметры должны стоять в конце списка — после них необязательные аргументы при вызове можно опускать. Внутри процедуры проверяйте, что передано: если вызывающий код опустил необязательный параметр без значения по умолчанию, в него попадёт Неопределено.
Практическое правило: параметры-объекты большого размера (таблицы значений, структуры) передавайте без Знач, чтобы не тратить ресурсы на копирование, но не изменяйте их внутри процедуры, если вызывающий код этого не ожидает. Намерение изменить параметр должно читаться из имени процедуры.
Директивы компиляции: где выполняется код
В модулях форм и команд перед объявлением процедуры указывается директива компиляции. Она определяет, в каком контексте будет скомпилирован и выполнен код:
&НаКлиенте— выполняется на клиенте, недоступны запросы к базе данных напрямую;&НаСервере— выполняется на сервере, нельзя использовать интерактивные диалоги с пользователем;&НаСервереБезКонтекста— серверная процедура без данных формы, вызывается быстрее, но реквизиты формы нужно передавать параметрами;&НаКлиентеНаСервереБезКонтекста— общий код, доступный в обоих контекстах.
Типовой сценарий в управляемой форме: клиентская процедура обрабатывает событие, вызывает серверную для обращения к данным, получает результат и обновляет элементы формы. Прямой вызов клиентской процедуры с сервера невозможен — это ограничение архитектуры.
&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
ПересчитатьСтрокуНаСервере(Элементы.Товары.ТекущаяСтрока);
КонецПроцедуры
&НаСервере
Процедура ПересчитатьСтрокуНаСервере(ИдентификаторСтроки)
Строка = Объект.Товары.НайтиПоИдентификатору(ИдентификаторСтроки);
Строка.Сумма = Строка.Количество * Строка.Цена;
КонецПроцедуры
Экспортные процедуры и общие модули
Процедура, объявленная в модуле формы или объекта, по умолчанию видна только внутри этого модуля. Чтобы сделать её доступной извне, после списка параметров добавляют ключевое слово Экспорт. В общих модулях экспортные процедуры образуют программный интерфейс, который может вызывать любой другой код конфигурации.
Общий модуль создаётся в ветке «Общие → Общие модули» конфигуратора. В его свойствах задают флаги контекста: «Сервер», «Клиент (управляемое приложение)», «Вызов сервера» и другие. Если модуль серверный и должен вызываться с клиента, обязательно включите «Вызов сервера», иначе обращение с клиента выдаст ошибку.
// Общий модуль РасчетыСервер
Функция РассчитатьНДС(Сумма, Ставка) Экспорт
Возврат Сумма * Ставка / (100 + Ставка);
КонецФункции
// Вызов из любого модуля:
НДС = РасчетыСервер.РассчитатьНДС(12000, 20);
Правило размещения: логика, нужная в одном объекте, живёт в модуле этого объекта; логика, используемая в нескольких местах, выносится в общий модуль. Дублирование одинаковых процедур в разных модулях — прямой путь к рассинхронизации поведения при доработках.
- 1Создайте общий модуль и установите нужные флаги контекста (Сервер, Вызов сервера)
- 2Объявите процедуру с понятным именем и параметрами, добавьте Экспорт
- 3Реализуйте тело, не обращаясь к глобальному контексту формы
- 4Вызовите процедуру из нужного места через ИмяМодуля.ИмяПроцедуры
- 5Проверьте выполнение под отладчиком в обоих контекстах — клиентском и серверном
Процедура или функция: что выбрать
Функция отличается тем, что возвращает значение оператором Возврат Значение; и может использоваться в выражениях. Если результат работы кода нужен вызывающей стороне — пишите функцию. Если код только выполняет действие (записывает объект, выводит сообщение, формирует движения) — достаточно процедуры.
Сравнение вариантов
Действие без результата: запись объекта, заполнение табличной части, вывод на печать. Нельзя использовать в выражениях.
Нужен результат: расчёт суммы, проверка заполнения с ответом Истина/Ложь, получение данных. Можно вызывать в составе выражений.
Компромисс, когда результатов несколько. Читабельность ниже — применяйте осознанно и документируйте комментарием.
Частая ошибка — функция, которая формально возвращает значение, но по факту выполняет действие и меняет состояние системы. Такой код трудно читать: вызов внутри выражения выглядит безобидным, а на деле записывает данные. Разделяйте: функции вычисляют, процедуры изменяют.
Отладка и проверка результата
Отладка процедур выполняется через конфигуратор: установите точку останова на нужной строке, запустите отладку (F5) и воспроизведите действие в клиентском приложении. По F10 выполняется шаг без захода внутрь вызываемых процедур, по F11 — с заходом внутрь. Значения переменных смотрятся в табло (Shift+F9) или вычислением выражения.
Проверять результат удобно по контрольным точкам: значения параметров на входе, состояние переменных после ключевых операторов, итоговый эффект в базе данных. Для серверных процедур убедитесь, что отладка на сервере разрешена (параметр запуска сервера или флаг в настройках информационной базы).
Как проверить результат
Код доходит до точки останова внутри процедуры
Точка не срабатывает — проверьте директиву компиляции и доступность модуля
Значения соответствуют ожиданиям вызывающего кода
Неопределено или неверный тип — ошибка в месте вызова
Данные записаны корректно и в нужном объекте
Изменений нет или записались лишние данные — ошибка в логике тела
Типичные ошибки при написании процедур
Ещё одна распространённая проблема — именование. Процедура с именем Обработать или Кнопка1Нажатие не говорит, что она делает, и через месяц смысл придётся восстанавливать по коду. Имя должно начинаться с глагола и описывать действие: ЗаполнитьЦеныПоВидуЦен, ПроверитьЗаполнениеКонтрагента.
Избегайте и скрытых зависимостей: процедура, которая молча читает глобальную переменную или реквизит формы, ведёт себя по-разному в зависимости от места вызова. Всё, что нужно процедуре для работы, должно приходить через параметры — тогда её поведение предсказуемо и проверяемо.
Что важно запомнить
Процедура объявляется с параметрами и завершается КонецПроцедуры; Знач защищает параметр от изменения; директива компиляции определяет контекст выполнения; для вызова извне нужны Экспорт и общий модуль с корректными флагами; действие без результата — процедура, вычисление — функция.
Частые вопросы о процедурах в 1С
Чем процедура отличается от функции?
Функция возвращает значение оператором Возврат и может стоять в выражениях и правой части присваивания. Процедура только выполняет действия. Если нужен результат работы — используйте функцию, если нужно действие — процедуру.
Как передать в процедуру табличную часть документа?
Передайте её как обычный параметр: Рассчитать(Объект.Товары). Внутри процедуры табличная часть доступна для перебора в цикле Для Каждого. Изменения строк будут видны вызывающему коду, так как объект передаётся по ссылке.
Почему процедура из общего модуля не вызывается с клиента?
Наиболее вероятные причины: не установлен флаг «Вызов сервера» в свойствах серверного общего модуля, пропущено ключевое слово Экспорт у процедуры или модуль не скомпилирован после изменений. Проверьте все три пункта.
Можно ли вызвать процедуру с сервера на клиенте?
Напрямую нет. Серверный код может только вернуть результат, а клиентская процедура дальше обработает его сама. Исключение — оповещения через механизм Оповестить, но это асинхронный обмен, а не прямой вызов.
Что делает ключевое слово Знач перед параметром?
Оно заставляет передать копию значения вместо ссылки. Изменения такого параметра внутри процедуры не затронут переменную вызывающего кода. Применяйте Знач, когда процедура должна работать с собственной копией данных.
Сколько параметров может быть у процедуры?
Явного жёсткого ограничения для практических задач нет, но список длиннее пяти-семи параметров — признак плохого дизайна. В таком случае сгруппируйте связанные данные в структуру и передавайте её одним параметром.