Глиф Учебники

Урок 6. Процедуры, функции и модули

Курс «1С:Предприятие» · урок 6 из 9 · 4 минуты чтения

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

Процедура и функция

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

1С
&НаКлиенте
Функция СуммаСоСкидкой(Сумма, Скидка)
    Возврат Сумма - Сумма * Скидка / 100;
КонецФункции

&НаКлиенте
Процедура ПоказатьИтог(Сумма)
    Сообщить("К оплате: " + Сумма);
КонецПроцедуры

&НаКлиенте
Процедура Пример(Команда)
    Итог = СуммаСоСкидкой(200, 10);
    ПоказатьИтог(Итог);
КонецПроцедуры
Вывод
К оплате: 180

Порядок в модуле не важен: процедура может вызывать ту, что описана ниже. Но имена в одном модуле не повторяются. Выйти из процедуры раньше конца можно словом Возврат; без значения.

Параметры: по ссылке и Знач

По умолчанию параметр передаётся по ссылке: если процедура изменит его, изменится и переменная того, кто её вызвал. Слово Знач перед параметром передаёт копию значения:

1С
&НаКлиенте
Процедура Удвоить(Число1, Знач Число2)
    Число1 = Число1 * 2;
    Число2 = Число2 * 2;
КонецПроцедуры

&НаКлиенте
Процедура Пример(Команда)
    А = 5;
    Б = 5;
    Удвоить(А, Б);
    Сообщить("А = " + А + ", Б = " + Б);
КонецПроцедуры
Вывод
А = 10, Б = 5
Пример переменные А 5 → 10 Б 5 Удвоить параметры по ссылке Число1 своей ячейки нет — это А копия 5 → 10 Знач Число2 своя копия Удвоить(А, Б); А = 10, Б = 5
Параметр Число1 передан по ссылке и меняет саму переменную А, поэтому А становится 10, а Знач Число2 получает копию значения Б, и Б остаётся 5.

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

1С
Функция Приветствие(Имя, Обращение = "Здравствуйте")
    Возврат Обращение + ", " + Имя + "!";
КонецФункции

Вызов Приветствие("Анна") вернёт «Здравствуйте, Анна!», а Приветствие("Анна", "Добрый день") — «Добрый день, Анна!».

Клиент и сервер

1С:Предприятие работает в двух местах. Клиент — программа на компьютере пользователя: показывает формы, реагирует на кнопки. Сервер — там, где лежат данные: в файловом варианте его роль выполняет та же программа, в клиент-серверном — отдельный сервер 1С:Предприятия.

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

ДирективаГде выполняется
&НаКлиентена клиенте: работа с формой, сообщения, диалоги
&НаСерверена сервере, с данными формы
&НаСервереБезКонтекстана сервере, без данных формы — быстрее, параметры передаются явно

Обычная связка: обработчик кнопки на клиенте вызывает серверную процедуру, а та работает с данными.

1С
&НаСервереБезКонтекста
Функция КоличествоТоваров()
    Количество = 0;
    Выборка = Справочники.Товары.Выбрать();
    Пока Выборка.Следующий() Цикл
        Количество = Количество + 1;
    КонецЦикла;
    Возврат Количество;
КонецФункции

&НаКлиенте
Процедура Пример(Команда)
    Сообщить("Товаров в справочнике: " + КоличествоТоваров());
КонецПроцедуры

Каждый вызов сервера — передача данных по сети. Не вызывайте сервер в цикле по одной строке: соберите всё нужное за один вызов.

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

Код в этом примере обращается к справочнику Товары из урока Конфигуратор: объекты конфигурации. Запустите обработку в учебной базе «Склад» — в другой базе такого справочника нет.

Общие модули и Экспорт

Общий модуль — ветка «Общие» → «Общие модули» в дереве конфигурации. В нём хранят процедуры, которые нужны в разных местах. Чтобы процедуру было видно снаружи модуля, после её заголовка пишут Экспорт:

1С
Функция ЦенаСНДС(Цена, Ставка) Экспорт
    Возврат Окр(Цена * (100 + Ставка) / 100, 2);
КонецФункции

Вызов — через имя модуля: РаботаСЦенами.ЦенаСНДС(100, 20). В свойствах общего модуля флажками задают, где он доступен: Сервер, Клиент (управляемое приложение), Вызов сервера (разрешает вызывать серверный модуль прямо с клиента). Окр(Число, 2) округляет до двух знаков после запятой.

Попытка и Исключение

Если во время выполнения случается ошибка — деление на ноль, файл не найден, — платформа останавливает код и показывает сообщение. Чтобы обработать ошибку самому, код ставят в блок Попытка:

1С
&НаКлиенте
Процедура Пример(Команда)
    Делитель = 0;
    Попытка
        Результат = 10 / Делитель;
        Сообщить(Результат);
    Исключение
        Сообщить("Не получилось: " + ОписаниеОшибки());
    КонецПопытки;
    Сообщить("Работа продолжается");
КонецПроцедуры

ОписаниеОшибки() возвращает текст ошибки, в нём будет «Деление на 0». Самому сообщить об ошибке и прервать работу можно инструкцией ВызватьИсключение "Не указан склад";.

Не прячьте ошибки пустым блоком Исключение: программа будет молча работать неправильно, и причину никто не найдёт. Сообщите пользователю, что случилось.

Структура и Соответствие

Два полезных вида значений, которые часто передают в процедуры и возвращают из функций:

1С
&НаКлиенте
Процедура Пример(Команда)
    Товар = Новый Структура("Наименование, Цена", "Карандаш", 2);
    Товар.Вставить("Количество", 10);
    Сообщить(Товар.Наименование + ": " + Товар.Цена * Товар.Количество);

    Цены = Новый Соответствие;
    Цены.Вставить("Ручка", 3);
    Сообщить("Ручка стоит " + Цены["Ручка"]);
КонецПроцедуры
Вывод
Карандаш: 20
Ручка стоит 3

Структура — набор именованных полей: ключи — имена, к ним обращаются через точку. Соответствие — пары «ключ — значение», где ключом может быть что угодно: строка, число, ссылка на товар. Если ключа нет, Цены["Хлеб"] вернёт Неопределено, а обращение к несуществующему полю структуры — ошибку «Поле объекта не обнаружено». Проверить поле заранее можно методом Свойство: Если Товар.Свойство("Цена") Тогда.

Структура Товар поля с именами, доступ через точку НаименованиеЦенаКоличество "Карандаш"210 Вставить Товар.Цена → 2 нет такого поля — ошибка «Поле объекта не обнаружено» Соответствие Цены ключ — строка, число, ссылка "Ручка" 3 ключ → значение "Хлеб" такого ключа нет Цены["Ручка"] → 3 Цены["Хлеб"] → Неопределено
У структуры Товар поля с именами, и обращение к несуществующему полю — ошибка, а соответствие Цены ищет значение по ключу и для отсутствующего ключа «Хлеб» возвращает Неопределено.

Коротко

Проверьте себя

1. Чем функция отличается от процедуры?
2. Процедура Удвоить(Знач Х) умножает Х на 2. Чему будет равна переменная после А = 5; Удвоить(А);?
3. Почему обработчик кнопки с &НаКлиенте не может сам выбрать товары из справочника?
4. Что нужно написать после заголовка функции общего модуля, чтобы вызвать её из формы?