Как объявлять, вызывать и отлаживать функции во встроенном языке 1С:Предприятия 8.3

· 10 мин

Содержание

Функция во встроенном языке 1С объявляется так: Функция Имя(Параметры), внутри — код и оператор Возврат Значение;, в конце — КонецФункции. От процедуры она отличается только тем, что возвращает результат, поэтому её можно вызвать прямо в выражении: Сумма = РассчитатьСкидку(Цена, 10);. Чтобы использовать функцию из другого модуля, добавьте после списка параметров слово Экспорт.

Всё, что ниже, относится к платформе 1С:Предприятие 8.3 и не зависит от конфигурации: правила одинаковы в Бухгалтерии, ЗУП, УТ и в собственной разработке. Разберём синтаксис, параметры, возврат значений, встроенные функции платформы, рекурсию, обработку ошибок и то, что тормозит вызовы в клиент-серверном режиме.

Как объявить функцию в 1С и где её видно

Минимальная функция выглядит так:

Функция РассчитатьСкидку(Цена, Процент)
	Возврат Цена * Процент / 100;
КонецФункции

Из чего состоит объявление:

  • 🔹 Имя — латиница или кириллица, без пробелов, не начинается с цифры. По соглашениям 1С имена пишут слитно с заглавной буквы каждого слова: ПолучитьОстатокТовара.
  • 🔹 Параметры — через запятую в скобках. Скобки ставятся, даже если параметров нет: Функция ТекущийПользователь().
  • 🔹 Экспорт — делает функцию доступной снаружи модуля.
  • 🔹 Директива компиляции — строка над объявлением в модулях форм и команд: &НаКлиенте, &НаСервере, &НаСервереБезКонтекста, &НаКлиентеНаСервереБезКонтекста.

Область видимости функции

Где функцию можно вызвать, зависит от модуля и от слова Экспорт.

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

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

Переменные внутри функции

Локальная переменная появляется при первом присваивании. Явно её объявляют оператором Перем в начале тела. Локальные переменные живут только на время вызова.

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

Параметры: по ссылке, по значению и необязательные

По умолчанию параметр передаётся по ссылке. Если функция присвоит параметру новое значение, оно изменится и в вызывающем коде.

Процедура Увеличить(Число)
	Число = Число + 1;
КонецПроцедуры

А = 5;
Увеличить(А);  // теперь А = 6

Слово Знач перед параметром включает передачу по значению: функция работает с копией, а исходная переменная не меняется.

Функция Удвоить(Знач Число)
	Число = Число * 2;
	Возврат Число;
КонецФункции

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

Значения по умолчанию

Необязательный параметр получает значение по умолчанию прямо в объявлении:

Функция Округлить(Сумма, Разрядов = 2)
	Возврат Окр(Сумма, Разрядов);
КонецФункции

Округлить(10.456);     // 10.46
Округлить(10.456, 0);  // 10

Необязательные параметры ставят в конец списка. Пропустить параметр в середине можно запятой: СоздатьЗапись(Ссылка, , Истина). Такой вызов плохо читается, поэтому при 4-5 необязательных параметрах лучше передать одну Структура с настройками.

Как функция 1С возвращает значение

Оператор Возврат сразу завершает функцию и отдаёт результат. Код после него в этой ветке не выполняется. Ранний выход упрощает проверки:

Функция ЦенаСоСкидкой(Цена, Процент)
	Если Цена <= 0 Тогда
		Возврат 0;
	КонецЕсли;
	Если Процент > 100 Тогда
		Процент = 100;
	КонецЕсли;
	Возврат Цена - Цена * Процент / 100;
КонецФункции

Правила возврата:

  1. Функция может вернуть значение любого типа: число, строку, ссылку, массив, структуру, таблицу значений.
  2. Если выполнение дошло до КонецФункции без Возврат, функция вернёт Неопределено.
  3. Функцию можно вызвать как процедуру — результат просто отбросится: ЦенаСоСкидкой(100, 5);.
  4. Процедуру как функцию вызвать нельзя: Х = Увеличить(А); не пройдёт синтаксический контроль.
  5. В процедуре Возврат пишут без значения — он просто прерывает выполнение.

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

Одним Возврат отдают одно значение. Если нужно несколько, есть два способа.

Структура — понятный и рекомендуемый:

Функция ИтогиПоДокументу(Документ)
	Результат = Новый Структура("Сумма, СуммаНДС, Количество", 0, 0, 0);
	Для Каждого Строка Из Документ.Товары Цикл
		Результат.Сумма = Результат.Сумма + Строка.Сумма;
		Результат.СуммаНДС = Результат.СуммаНДС + Строка.СуммаНДС;
		Результат.Количество = Результат.Количество + Строка.Количество;
	КонецЦикла;
	Возврат Результат;
КонецФункции

Итоги = ИтогиПоДокументу(ДокОбъект);
Сообщить(Итоги.СуммаНДС);

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

Встроенные функции 1С для работы с данными

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

Строки

Строка = "  ООО Ромашка; ИНН 7701234567  ";
Чистая = СокрЛП(Строка);                     // убирает пробелы по краям
Длина = СтрДлина(Чистая);
Части = СтрРазделить(Чистая, ";");           // массив из 2 строк
Поз = СтрНайти(Чистая, "ИНН");               // позиция подстроки, 0 если нет
ИНН = СокрЛП(Сред(Чистая, Поз + 3));         // "7701234567"
Текст = СтрШаблон("Контрагент %1, ИНН %2", СокрЛП(Части[0]), ИНН);

СтрНайти, СтрРазделить, СтрСоединить и СтрШаблон появились в 8.3.6. В старом коде вместо них встречаются Найти и разбор строки циклом.

Числа и даты

Окр(1234.567, 2);        // 1234.57
Цел(7.9);                // 7
Макс(3, 8, 5);           // 8
НачалоМесяца(ТекущаяДатаСеанса());
ДобавитьМесяц('20260131', 1);   // 28.02.2026 — последний день февраля

Для серверной логики берите ТекущаяДатаСеанса(), а не ТекущаяДата(): первая учитывает часовой пояс сеанса, вторая возвращает время компьютера, где выполняется код.

Типы и преобразования

  • 🔸 ТипЗнч(Значение) = Тип("Число") — проверка типа.
  • 🔸 ЗначениеЗаполнено(Значение) — пустая ли ссылка, строка, дата, ноль.
  • 🔸 Число("12.5"), Строка(42), Дата("20260101"), Булево(1) — преобразования. Число() на строке «12,5 руб.» вызовет исключение.
  • 🔸 Формат(1234567.8, "ЧДЦ=2; ЧГ=0") — число без пробелов-разделителей: 1234567.80.

Склеивая число со строкой, всегда используйте Формат или СтрШаблон. Иначе "Код " + 1500 даст Код 1 500 с неразрывным пробелом, и такой код не найдётся в базе.

Собственные функции и рекурсия в 1С

Свою функцию выносят тогда, когда один и тот же кусок кода нужен в 2-3 местах или когда процедура перевалила за экран. Хорошая функция делает одно дело и называется глаголом: ПолучитьКурсВалюты, ПроверитьЗаполнениеИНН.

Где хранить:

  • 📁 логика одного документа — в модуле объекта или менеджера;
  • 📁 общая логика для многих объектов — в общем модуле с понятным именем;
  • 📁 код для внешних обработок и отчётов — в модуле самой обработки.

Рекурсия: функция вызывает сама себя

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

Функция КоличествоСтрокДерева(СтрокиДерева)
	Всего = 0;
	Для Каждого Строка Из СтрокиДерева Цикл
		Всего = Всего + 1 + КоличествоСтрокДерева(Строка.Строки);
	КонецЦикла;
	Возврат Всего;
КонецФункции

Количество = КоличествоСтрокДерева(Дерево.Строки);

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

Рекурсия без условия выхода роняет сеанс. Глубина стека вызовов ограничена, при её превышении платформа прерывает выполнение с ошибкой. Если иерархия в данных может быть зациклена (элемент ссылается на себя как на родителя), передавайте в рекурсию счётчик уровня и останавливайтесь, например, на 100.

Для иерархических справочников рекурсия часто не нужна вовсе: запрос с условием В ИЕРАРХИИ получает все вложенные элементы одним обращением к базе.

Сводная таблица функций для разработчика

ЗадачаФункция или конструкцияПример
Объявить функциюФункция … КонецФункцииФункция Итог(А, Б)
Открыть для других модулейЭкспортФункция Итог(А, Б) Экспорт
Защитить параметр от измененияЗначФункция Ф(Знач Сумма)
Необязательный параметр= значениеФункция Ф(Сумма, НДС = 20)
Вернуть результатВозвратВозврат Сумма * 1.2;
Убрать пробелыСокрЛПСокрЛП(" ИНН ")
Разбить строкуСтрРазделитьСтрРазделить(Стр, ",")
Подставить значения в текстСтрШаблонСтрШаблон("%1 руб.", Сумма)
ОкруглитьОкрОкр(Сумма, 2)
Сдвинуть дату на месяцыДобавитьМесяцДобавитьМесяц(Дата, -1)
Проверить типТипЗнч, ТипТипЗнч(Х) = Тип("Строка")
Проверить пустотуЗначениеЗаполненоЗначениеЗаполнено(Контрагент)
Вывести число как текстФорматФормат(Код, "ЧГ=0")
Перехватить ошибкуПопытка … Исключениесм. ниже
Сгенерировать ошибкуВызватьИсключениеВызватьИсключение "Не задан склад";
Текст ошибкиОписаниеОшибки()внутри блока Исключение
Проверьте себя
Что вернёт функция, если выполнение дошло до КонецФункции без оператора Возврат?
Параметр объявлен как Знач Таблица, функция добавила в таблицу строку. Что увидит вызывающий код?
Флажок какого свойства нужен общему серверному модулю, чтобы его функцию можно было вызвать с клиента?

Ошибки внутри функций: Попытка, Исключение и отладка

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

Функция ЧислоИзСтроки(Текст)
	Попытка
		Возврат Число(Текст);
	Исключение
		ЗаписьЖурналаРегистрации("Преобразование числа",
			УровеньЖурналаРегистрации.Предупреждение, , ,
			ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		Возврат 0;
	КонецПопытки;
КонецФункции

Что важно при перехвате:

  • ❗ Не глушите ошибки молча. Пустой блок Исключение прячет проблему, и потом неделями ищут, почему сумма ноль. Минимум — запись в журнал регистрации.
  • ❗ Транзакцию начинают до Попытка, а в блоке Исключение отменяют и пробрасывают ошибку дальше:
НачатьТранзакцию();
Попытка
	ЗаписатьДвижения(Документ);
	ЗафиксироватьТранзакцию();
Исключение
	ОтменитьТранзакцию();
	ВызватьИсключение;
КонецПопытки;
  • ❗ ВызватьИсключение без текста внутри блока Исключение пробрасывает исходную ошибку со всеми подробностями. С текстом — создаёт новую ошибку с вашим сообщением.

Свою ошибку для пользователя генерируют так: ВызватьИсключение "Не указан склад в строке " + Формат(НомерСтроки, "ЧГ=0");.

Отладка функции в Конфигураторе

  1. Поставьте точку останова на строке внутри функции клавишей F9.
  2. Запустите отладку: Отладка → Начать отладку → 1С:Предприятие или клавишей F5.
  3. Выполните в пользовательском режиме действие, которое вызывает функцию.
  4. Когда выполнение остановится, ходите по шагам: F11 — с заходом в вызываемую функцию, F10 — без захода, Shift+F11 — выйти из текущей функции.
  5. Значение любого выражения смотрите через Shift+F9 или добавьте переменную в окно «Табло».
  6. Окно «Стек вызовов» покажет, через какую цепочку функций вы сюда попали — так находят, кто передал неверный параметр.

Если точка останова в серверной функции не срабатывает в клиент-серверной базе, проверьте, что на сервере 1С включена отладка. Без этого остановятся только клиентские функции.

Как ускорить вызовы функций в клиент-серверном режиме

Сама по себе функция работает быстро. Время уходит на две вещи: вызовы сервера с клиента и обращения к базе.

Сократите число вызовов сервера

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

Что помогает:

  • ⚡ Собрать работу в одну серверную функцию и вызвать её один раз.
  • ⚡ Использовать &НаСервереБезКонтекста, если функции не нужны реквизиты формы: данные формы тогда не передаются, а всё нужное идёт через параметры.
  • ⚡ Объявлять параметры серверных функций, вызываемых с клиента, через Знач. Параметры без Знач после вызова возвращаются на клиент, а это лишний трафик.

Не обращайтесь к базе в цикле

Типичный тормоз — запрос или чтение реквизита через точку внутри цикла:

// Медленно: на каждой строке отдельное чтение объекта
Для Каждого Строка Из Товары Цикл
	Если Строка.Номенклатура.Услуга Тогда
		...
	КонецЕсли;
КонецЦикла;

Обращение Ссылка.Реквизит читает объект из базы. На 1000 строк — 1000 обращений. Правильнее получить нужные реквизиты всех товаров одним запросом до цикла, а в цикле искать в полученной таблице. В типовых конфигурациях на БСП для этого есть функции общего модуля ОбщегоНазначения, например ЗначенияРеквизитовОбъектов.

Кэшируйте то, что не меняется

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

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

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

Чем функция отличается от процедуры в 1С?
Функция возвращает значение через оператор Возврат и может стоять в выражении. Процедура ничего не возвращает и вызывается отдельной строкой.
Можно ли вызвать функцию по имени из строки?
Да, через Вычислить или Выполнить, но так делают только при крайней необходимости: код не проверяется при сохранении и уязвим к подстановке. В типовых на БСП для этого есть ОбщегоНазначения.ВыполнитьМетодКонфигурации с проверкой имени.
Как сделать асинхронную функцию?
С платформы 8.3.18 есть ключевые слова Асинх и Ждать: функция объявляется как Асинх Функция, внутри можно ждать результат, например ответ на ВопросАсинх, без отдельной процедуры-обработчика оповещения.
Почему функция общего модуля не видна в форме?
Проверьте три вещи: слово Экспорт в объявлении, флажок Клиент у модуля для клиентского кода или Вызов сервера для серверного, и директиву компиляции в месте вызова.
Сколько параметров может быть у функции?
Жёсткого предела на практике нет, но больше 5-7 параметров делают вызов нечитаемым. Передавайте настройки одной структурой.