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

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

Как писать функции в 1С: руководство для разработчика

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

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

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

Материал рассчитан на разработчиков, которые уже знакомы с конфигуратором 1С и хотят системно разобраться в написании функций: от объявления и параметров до экспорта, директив компиляции и типичных ошибок.

Синтаксис объявления функции

Функция объявляется в модуле между ключевыми словами Функция и КонецФункции. После имени в скобках перечисляются параметры, а тело функции содержит произвольный код на встроенном языке. Результат возвращается оператором Возврат.

Функция РассчитатьСуммуСНДС(Сумма, СтавкаНДС) Экспорт

Если СтавкаНДС = 0 Тогда

Возврат Сумма;

КонецЕсли;

Возврат Сумма + Сумма * СтавкаНДС / 100;

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

Имя функции должно быть осмысленным и отражать результат: РассчитатьСуммуСНДС, ПолучитьКурсВалюты, СформироватьТекстЗапроса. Избегайте имён вида Ф1 или ОбработкаДанных — через месяц такой код не поймёт даже автор.

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

Чем функция отличается от процедуры

Ключевое различие — возврат значения. Процедура выполняет действия и ничего не возвращает, функция обязана вернуть результат. Поэтому функцию можно вставить прямо в выражение: Итог = РассчитатьСуммуСНДС(База, 20) * Количество;, а процедуру — нет.

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

Функция или процедура

Функция

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

Процедура

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

Функция с возвратом Булево

Для проверок: ДокументПроведен(), ЕстьПраваДоступа(). Удобно использовать прямо в условии Если.

Параметры: значения по умолчанию и передача по ссылке

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

Функция ПолучитьЦену(Номенклатура, Дата = Неопределено) Экспорт

Если Дата = Неопределено Тогда

Дата = ТекущаяДатаСеанса();

КонецЕсли;

// дальше расчёт цены на дату

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

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

Пропуск параметров при вызове выполняется через запятые: МояФункция(Парам1, , Парам3) — второй параметр получит значение по умолчанию или Неопределено. Однако злоупотреблять пропусками не стоит: вызов с пятью запятыми подряд нечитаем. Если параметров больше трёх-четырёх, лучше передать структуру.

Ключевое слово Экспорт и область видимости

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

Экспортировать следует только те функции, которые действительно нужны снаружи. Вспомогательные «внутренние» функции оставляйте без Экспорт — так проще рефакторить модуль, не опасаясь сломать чужие вызовы. В типовых конфигурациях внутренние функции часто дополнительно помечают комментарием или размещают в области #Область СлужебныеПроцедурыИФункции.

Области видимости по типам модулей: функции модуля формы доступны только этой форме; функции модуля объекта — при работе с конкретным объектом; функции общего модуля с Экспорт — всей конфигурации. Именно общие модули — стандартное место для переиспользуемых функций.

Где размещать функции: общие модули и директивы

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

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

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

Порядок создания серверной функции в общем модуле
  1. 1
    Создайте общий модуль с понятным именем, например РаботаСНоменклатурой
  2. 2
    В свойствах модуля включите флаг Сервер и при необходимости Вызов сервера
  3. 3
    Объявите функцию с ключевым словом Экспорт и осмысленными параметрами
  4. 4
    Добавьте проверку входных параметров и оператор Возврат во всех ветках логики
  5. 5
    Вызовите функцию из нужного места: ИмяМодуля.ИмяФункции(Параметры)
  6. 6
    Проверьте работу в режиме отладки, поставив точку останова внутри функции

Возврат значений и обработка ошибок

Функция может вернуть значение любого типа: число, строку, булево, ссылку на объект, структуру, массив. Для сложных результатов удобна структура — например, функция проверки документа может вернуть структуру с полями «Успех», «ТекстОшибки», «КоличествоОшибок».

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

Функция НайтиДоговорПоНомеру(Номер) Экспорт

Если ПустаяСтрока(Номер) Тогда

ВызватьИсключение "Не передан номер договора";

КонецЕсли;

Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1 Договоры.Ссылка

|ИЗ Справочник.ДоговорыКонтрагентов КАК Договоры

|ГДЕ Договоры.Номер = &Номер";

Запрос.УстановитьПараметр("Номер", Номер);

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

Возврат Выборка.Ссылка;

КонецЕсли;

Возврат Неопределено;

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

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

Типичные ошибки при написании функций

Самая распространённая ошибка — отсутствие Возврат в одной из веток условия. Код компилируется, но при определённых входных данных функция возвращает Неопределено, и ошибка всплывает в вызывающем коде. Проверяйте каждую ветку Если и Иначе.

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

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

Типичные ошибки
01
Нет Возврат в одной из веток — функция возвращает Неопределено, ошибка проявляется в вызывающем коде
02
Забыто слово Экспорт — функция недоступна из других модулей, ошибка 'Процедура или функция с указанным именем не определена'
03
Серверная логика размещена в клиентском модуле — ошибка компиляции или недоступность запросов к базе
04
Изменение параметра-структуры внутри функции без ведома вызывающего кода — неочевидные побочные эффекты
05
Функция делает и вычисление, и запись в базу — невозможно переиспользовать и тестировать
06
Десяток параметров вместо структуры — вызовы нечитаемы, легко перепутать порядок

Отладка и проверка функций

Основной инструмент — отладчик конфигуратора. Поставьте точку останова на первой строке функции (F9), запустите отладку (F5) и выполните действие, которое вызывает функцию. По F11 заходите внутрь вызовов, по F10 шагаете построчно, в табло (Shift+F9) проверяйте значения переменных и параметров.

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

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

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

Возвращаемое значение
Норма

Функция возвращает ожидаемый тип при любых входных данных

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

При части входных данных возвращается Неопределено без явной причины

Поведение при ошибке
Норма

Понятное исключение с текстом или явный признак неудачи в результате

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

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

Вызов из других модулей
Норма

Функция с Экспорт вызывается и работает из всех нужных мест

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

Ошибка 'не определена' — не хватает Экспорт или флага Вызов сервера

Производительность
Норма

Функция в цикле не выполняет запросы к базе на каждой итерации

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

Запрос внутри функции вызывается тысячи раз — вынесите данные в одну выборку

FAQ: частые вопросы о функциях в 1С

Чем отличается Знач в параметрах функции?

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

Можно ли вызвать функцию до её объявления в модуле?

Да. В пределах одного модуля порядок объявления функций и процедур не важен: компилятор 1С сначала собирает все объявления, а потом выполняет код. Можно вызывать функцию, описанную ниже по тексту модуля.

Как вернуть из функции несколько значений?

Через структуру: создайте Новый Структура с именованными полями, заполните её и верните. Альтернатива — массив, но структура читаемее, так как у значений есть имена. Менять параметры-структуры, переданные в функцию, — работающий, но менее прозрачный приём.

Почему функция в общем модуле не видна из формы?

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

Нужно ли писать комментарии к функциям?

Да, особенно к экспортным. Стандарт разработки 1С рекомендует описывать назначение функции, параметры и возвращаемое значение в комментарии перед объявлением. Это помогает коллегам и упрощает сопровождение, а в типовых конфигурациях такие комментарии обязательны.

Что лучше: одна большая функция или несколько маленьких?

Несколько маленьких. Функция должна выполнять одну осмысленную операцию и умещаться на экране. Маленькие функции проще тестировать, переиспользовать и отлаживать. Если функция требует прокрутки на несколько экранов и содержит вложенные условия в четыре-пять уровней — её нужно разбивать.

Итог

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

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