Как назначить событие для кнопки и получить курс валюты в табличную часть 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

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

Проанализируем причину ошибки: Клиент, Сервер и Контекст

Главная особенность управляемых форм в 1С (версии 8.2 и 8.3) — это строгое разделение кода на клиентскую и серверную части. Проанализируем, как они взаимодействуют:

  1. Клиентская часть (обозначается директивой &НаКлиенте) — это всё, что видит пользователь. Сама форма, кнопки, поля ввода, а также события нажатия на эти кнопки "живут" на клиенте. Однако клиент ничего не знает о базе данных (справочниках, регистрах).
  2. Серверная часть (например, &НаСервереБезКонтекста) — имеет полный доступ к базе данных. Именно здесь мы можем получить курс валюты из регистра сведений.

В обсуждаемой проблеме разработчик пытался использовать директиву &НаСервереБезКонтекста. Разберем подробнее, что она означает. Эта директива заставляет сервер выполнить процедуру максимально быстро, не передавая на сервер саму форму (контекст). Сервер в этом случае становится «слепым»: он не видит ни табличную часть, ни элементы формы. Все данные, которые нужны серверу для работы, мы обязаны передать ему явно через параметры.

Основная ошибка заключалась в том, что в качестве параметра на сервер передавалась сама кнопка (элемент управления), а не данные. Сервер не умеет работать с элементами интерфейса, поэтому возникает сбой.

Разберем по шагам правильный алгоритм действий

Чтобы решить задачу, нам нужно разделить логику на два этапа. Сначала мы берем нужные данные на клиенте, затем передаем их на сервер, получаем результат и записываем его обратно в форму. Посмотрим на пример реализации.

Шаг 1. Пишем код на клиенте

В обработчике нажатия кнопки нам нужно получить данные той строки табличной части, на которой сейчас стоит курсор пользователя. Для этого используем свойство ТекущиеДанные элемента формы.


&НаКлиенте
Процедура ЗаполнитьКурсВалюты(Команда)
    
    // Получаем данные текущей выделенной строки табличной части
    ТекущаяСтрока = Элементы.ИмяВашейТабличнойЧасти.ТекущиеДанные;
    
    // Проверяем, что строка действительно выбрана и валюта заполнена
    Если ТекущаяСтрока = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    Если Не ЗначениеЗаполнено(ТекущаяСтрока.Валюта) Тогда
        Сообщить("Укажите валюту в строке!");
        Возврат;
    КонецЕсли;
    
    // Вызываем серверную функцию, передавая ей только нужные ДАННЫЕ (ссылку на валюту и дату)
    НовыйКурс = ПолучитьКурсВалютыНаСервере(ТекущаяСтрока.Валюта, Объект.Дата);
    
    // Присваиваем полученный результат обратно в реквизит строки
    ТекущаяСтрока.Курс = НовыйКурс;
    
КонецПроцедуры

Шаг 2. Разрабатываем серверную функцию

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


&НаСервереБезКонтекста
Функция ПолучитьКурсВалютыНаСервере(ВыбраннаяВалюта, ДатаДокумента)
    
    // Формируем запрос к виртуальной таблице СрезПоследних
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   КурсыВалютСрезПоследних.Курс КАК Курс
        |ИЗ
        |   РегистрСведений.КурсыВалют.СрезПоследних(&Период, Валюта = &Валюта) КАК КурсыВалютСрезПоследних";
        
    Запрос.УстановитьПараметр("Период", ДатаДокумента);
    Запрос.УстановитьПараметр("Валюта", ВыбраннаяВалюта);
    
    РезультатЗапроса = Запрос.Выполнить();
    Если Не РезультатЗапроса.Пустой() Тогда
        Выборка = РезультатЗапроса.Выбрать();
        Выборка.Следующий();
        Возврат Выборка.Курс;
    КонецЕсли;
    
    // Если курс не найден, возвращаем единицу по умолчанию
    Возврат 1; 
    
КонецФункции

Оптимизация: Использование Библиотеки стандартных подсистем (БСП)

Если вы работаете в современной типовой конфигурации 1С (такой как Бухгалтерия предприятия, Управление торговлей или ERP), писать собственный запрос к регистру сведений не всегда целесообразно. В этих конфигурациях встроена Библиотека стандартных подсистем (БСП), которая предоставляет готовые общие модули для решения стандартных задач.

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


&НаСервереБезКонтекста
Функция ПолучитьКурсВалютыНаСервере(ВыбраннаяВалюта, ДатаДокумента)
    
    // Используем типовую функцию БСП для получения курса
    Возврат РаботаСКурсамиВалют.ПолучитьКурсВалюты(ВыбраннаяВалюта, ДатаДокумента);
    
КонецФункции

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

Подведем итоги

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

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

← На главную