Работа с функциями в 1С:Предприятие — основа любой автоматизации бизнес-процессов. Однако даже опытные разработчики иногда сталкиваются с проблемами при попытке получить результат выполнения функции. В отличие от процедур, функции обязательно возвращают значение, но способы его извлечения и обработки зависят от контекста: это может быть простое число, сложная структура данных или даже объект с методами. Ошибки на этом этапе приводят к падению производительности, некорректным отчётам или сбоям в обмене данными.

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

1. Базовый синтаксис: оператор Возврат и присваивание результата

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

Функция СуммаЧисел(Число1, Число2)

Возврат Число1 + Число2;

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

// Вызов функции и сохранение результата

Результат = СуммаЧисел(5, 10); // Результат = 15

Здесь значение 15 возвращается в переменную Результат. Важно понимать, что Возврат не только передаёт данные, но и прерывает выполнение функции — все команды после него игнорируются. Это полезно для досрочного выхода из цикла или условного блока:

Функция ПроверкаПоложительногоЧисла(Значение)

Если Значение <= 0 Тогда

Возврат Ложь; // Досрочный выход

КонецЕсли;

Возврат Истина;

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

💡

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

Ошибка многих новичков — попытка вернуть значение через параметр вместо Возврат. Например, такой код некорректен:

// НЕПРАВИЛЬНО!

Функция НеправильнаяФункция(Результат)

Результат = 100;

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

Чтобы передать данные через параметр, его нужно объявить с ключевым словом Перем или использовать параметры по ссылке (разберём далее).

2. Работа с параметрами по ссылке: когда и как использовать

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

Процедура ИзменитьЗначение(ЗначениеПоСсылке)

ЗначениеПоСсылке = ЗначениеПоСсылке * 2;

КонецПроцедуры

// Вызов

Переменная = 5;

ИзменитьЗначение(Переменная); // Теперь Переменная = 10

Однако в функции тоже могут использовать параметры по ссылке параллельно с оператором Возврат. Например:

Функция РазделитьИОкруглить(Число, Остаток Перем ОстатокВычисления)

ОстатокВычисления = Число % 2;

Возврат Цел(Число / 2);

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

// Вызов

ЦелаяЧасть = РазделитьИОкруглить(7, Остаток);

// ЦелаяЧасть = 3, Остаток = 1

  • 🔹 Плюсы: можно вернуть несколько значений без создания сложных структур.
  • 🔸 Минусы: код становится менее прозрачным, сложнее отлаживать.
  • 🔶 Рекомендация: используйте параметры по ссылке только когда это оправдано (например, для оптимизации производительности).
📊 Как часто вы используете параметры по ссылке в 1С?
Часто, это удобно
Рядом, только при необходимости
Никогда, предпочитаю структуры
Не знаю, что это

3. Динамический вызов функций: Выполнить() и Новый

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

ИмяФункции = "СуммаЧисел";

Параметры = Новый Массив;

Параметры.Добавить(5);

Параметры.Добавить(10);

Результат = Выполнить(ИмяФункции, Параметры); // 15

Это мощный инструмент, но он имеет существенные ограничения:

  • 🚨 Безопасность: Выполнить() может исполнять произвольный код, что опасно при работе с пользовательским вводом.
  • 🐢 Производительность: динамический вызов работает медленнее статического.
  • 🔍 Отладка: сложнее отслеживать ошибки.

Альтернатива — использование конструктора Новый для создания объектов с методами:

Калькулятор = Новый Калькулятор();

Результат = Калькулятор.Сумма(5, 10);

Чем опасен Выполнить() в 1С?

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

4. Обработка исключений: что делать, если функция вернула ошибку

Функции в могут завершаться не только успешным возвратом значения, но и исключением. Если его не обработать, программа аварийно завершит выполнение. Базовый синтаксис обработки:

Попытка

Результат = РискованнаяФункция();

Исключение

Сообщить("Ошибка: " + ОписаниеОшибки());

Результат = Неопределён; // или другое значение по умолчанию

КонецПопытки;

Типичные ошибки при работе с функциями:

Тип ошибки Причина Решение
Неопределён Функция не вернула значение явно Добавить Возврат в конце функции
Тип не совпадает Функция вернула строку, а ожидалось число Преобразовать тип (Число(), Строка())
Ошибка приведение типа Попытка присвоить несовместимые типы Использовать явное приведение или проверку ТипЗнч()

Для отладки полезно логировать входные параметры и возвращаемые значения:

Функция БезопасноеДеление(Делимое, Делитель)

Если Делитель = 0 Тогда

ЗаписатьЛог("Попытка деления на ноль! Делимое: " + Делимое);

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

КонецЕсли;

Возврат Делимое / Делитель;

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

💡

Всегда проверяйте входные параметры функции на корректность, особенно если они поступают из внешних источников (файлы, веб-сервисы, пользовательский ввод).

5. Оптимизация: кеширование и ленивые вычисления

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

Функция КешированнаяСумма(Число1, Число2)

Статическая Кеш = Новый Соответствие;

Ключ = Число1 + "|" + Число2;

Если Кеш.СодержитКлюч(Ключ) Тогда

Возврат Кеш[Ключ];

Иначе

Результат = Число1 + Число2;

Кеш.Вставить(Ключ, Результат);

Возврат Результат;

КонецЕсли;

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

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

Функция ЛенивоеВычисление()

Возврат Новый ЛенивыйРезультат();

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

// Использование

Результат = ЛенивоеВычисление();

Сообщить(Результат.Получить()); // Вычисление происходит здесь

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

☑️ Оптимизация функций в 1С

Выполнено: 0 / 4

6. Типовые ошибки и как их избежать

Даже простые функции могут стать источником ошибок, если не учитывать особенности . Рассмотрим самые распространённые случаи:

⚠️ Внимание: При передаче объектов (справочников, документов) в функцию по значению создаётся их копия, что может привести к неожиданному поведению. Используйте передачу по ссылке или явное клонирование.

Ошибка 1: Игнорирование контекста вызова

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

Ошибка 2: Изменение входных параметров

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

Функция ОбработатьМассив(Массив)

КопияМассива = Новый Массив;

КопияМассива.Загрузить(Массив);

// Работаем с КопияМассива

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

Ошибка 3: Возврат Неопределён без проверки

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

Результат = НайтиДанные();

Если Результат = Неопределён Тогда

Сообщить("Данные не найдены!");

Иначе

// Обработка результата

КонецЕсли;

7. Практический пример: получение данных из функции для отчёта

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

Функция ПолучитьДанныеДляОтчёта(ДатаНачала, ДатаКонца)

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

Запрос.Текст =

"ВЫБРАТЬ

| Документ.Ссылка КАК Ссылка,

| Документ.Сумма КАК Сумма

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Документ

|ГДЕ

| Документ.Дата МЕЖДУ &ДатаНачала И &ДатаКонца";

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

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

Возврат Запрос.Выполнить().Выгрузить();

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

Теперь используем её в отчёте:

Процедура СформироватьОтчёт()

Данные = ПолучитьДанныеДляОтчёта(НачалоМесяца(ТекущаяДата()), КонецМесяца(ТекущаяДата()));

Если Данные.Количество() = 0 Тогда

Предупреждение("Нет данных за указанный период!");

Возврат;

КонецЕсли;

// Формирование отчёта на основе Данные

Отчёт = Новый ТабличныйДокумент;

Отчёт.Вывести(Данные);

КонецПроцедуры

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

FAQ: Ответы на частые вопросы

Можно ли вернуть из функции массив и структуру одновременно?

Нет, функция в может вернуть только одно значение. Однако вы можете:

  • Использовать структуру с ключами "Массив" и "Данные".
  • Вернуть массив, где первый элемент — массив, а второй — структура.
  • Использовать параметры по ссылке для дополнительных данных.
Как узнать, что функция вернула ошибку, если нет исключения?

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

// Возвращает:

// - Массив данных при успехе

// - Неопределён, если данные не найдены

// - Ложь, если ошибка доступа

Почему функция работает медленно при большом количестве вызовов?

Возможные причины:

  • Отсутствует кеширование повторяющихся вычислений.
  • Функция выполняет тяжёлые операции (например, запросы к базе) без оптимизации.
  • Используются глобальные переменные, что замедляет доступ к данным.

Решение: профилируйте код с помощью ИзмерительПроизводительности и оптимизируйте "узкие места".

Можно ли вызвать функцию из другой базы 1С?

Да, для этого используйте:

  • COM-соединение (для файлового варианта).
  • HTTP-сервисы или OData (для клиент-серверного варианта).
  • Обмен через XML/JSON с промежуточным хранилищем.

Пример вызова через HTTP:

HTTPСервис = Новый HTTPСоединение("http://сервер/база/hs/servicename");

Ответ = HTTPСервис.ВыполнитьЗапрос("POST", "", Заголовки, ТелоЗапроса);

Как передать в функцию неограниченное количество параметров?

Используйте параметр типа Массив или аргументы переменной длины (в новых версиях платформы):

Функция Суммировать(Параметры)

Результат = 0;

Для Каждого Число Из Параметры Цикл

Результат = Результат + Число;

КонецЦикла;

Возврат Результат;

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

// Вызов

Сумма = Суммировать(Новый Массив(1, 2, 3, 4)); // 10