При начале работы с платформой 1С:Предприятие разработчики часто сталкиваются с задачей интерактивного взаимодействия с пользователем. Типичный сценарий: пользователь выбирает параметр на форме (например, руководителя), нажимает кнопку, а система должна выполнить запрос к базе данных и вывести результат в виде лаконичного информационного сообщения.
В этой статье мы подробно разберем, как реализовать этот функционал. Мы начнем с самого простого решения, которое помогло автору темы на форуме, а затем проанализируем профессиональные подходы: оптимизируем тяжелый запрос и рассмотрим современный стандарт разработки с использованием объекта СообщениеПользователю.
Рассмотрим по шагам все этапы реализации, от исправления ошибок в коде до тонкостей клиент-серверного взаимодействия.
---
Если перед нами стоит задача быстро вывести текстовую информацию на экран пользователя в обычной форме, самым простым и очевидным инструментом является встроенная функция Сообщить(). Она выводит переданную ей строку в специальное окно «Сообщения» в нижней части экрана.
Давайте проанализируем код функции, к которой пришел автор темы в процессе обсуждения на форуме. Функция принимает ссылку на руководителя, выполняет запрос к справочнику листов оценки, выгружает результат в таблицу значений и сообщает пользователю количество найденных записей:
Функция ПолучитьЛистОценки(мРуководитель)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КП_ОценкаСотрудника.Ссылка,
| КП_ОценкаСотрудника.Руководитель
|ИЗ
| Справочник.КП_ОценкаСотрудника КАК КП_ОценкаСотрудника
|ГДЕ
| КП_ОценкаСотрудника.Руководитель = &Руководитель";
Запрос.УстановитьПараметр("Руководитель", мРуководитель);
ТаблицаРезультата = Запрос.Perform().Unload(); // Выгружаем результат в Таблицу Значений
КоличествоЗаписей = ТаблицаРезультата.Количество();
Если КоличествоЗаписей = 0 Тогда
Сообщить("В выборке ноль листов оценки для данного руководителя.");
Возврат Ложь;
Иначе
Сообщить("У выбранного руководителя заполнено листов оценки: " + КоличествоЗаписей);
Возврат Истина;
КонецЕсли;
КонецФункции
Обратите внимание на конструкцию "" + КоличествоЗаписей или явное преобразование типов. В 1С при сложении строки и числа платформа автоматически преобразует число к строковому типу, что позволяет нам легко конструировать понятные динамические сообщения для пользователей.
---
Хотя предыдущее решение полностью работоспособно и решает задачу автора, оно имеет серьезную архитектурную проблему производительности. Метод Выгрузить() полностью переносит все найденные строки из базы данных в оперативную память сервера приложений в виде объекта ТаблицаЗначений.
Если у руководителя будут сотни или тысячи заполненных документов, система потратит колоссальное количество ресурсов на сериализацию данных, их передачу по сети и создание тяжелого объекта в памяти только ради того, чтобы узнать одну цифру — их количество.
Давайте выясним, как сделать это правильно. Подсчет количества нужно перенести на сторону СУБД (сервера баз данных), используя агрегатную функцию КОЛИЧЕСТВО() прямо в тексте запроса. В этом случае сервер базы данных вернет нам ровно одну строку с одним числом, что сработает мгновенно при любом объеме данных.
Перепишем нашу функцию с учетом правил оптимизации кода 1С:
Функция ПолучитьКоличествоЛистовОценки(мРуководитель)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(КП_ОценкаСотрудника.Ссылка) КАК КоличествоЛистов
|ИЗ
| Справочник.КП_ОценкаСотрудника КАК КП_ОценкаСотрудника
|ГДЕ
| КП_ОценкаСотрудника.Руководитель = &Руководитель";
Запрос.УстановитьПараметр("Руководитель", мРуководитель);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.КоличествоЛистов;
Иначе
Возврат 0;
КонецЕсли;
КонецФункции
Теперь функция возвращает не булево значение (Истина/Ложь), а реальное число документов. Это делает функцию более универсальной, так как мы сможем использовать полученное число и в других алгоритмах программы.
---
В современной разработке на платформе 1С (особенно при переходе на Управляемые формы) использовать метод Сообщить() напрямую крайне не рекомендуется стандартами разработки фирмы «1С». Ему на смену пришел специализированный объект СообщениеПользователю.
Разберем подробнее его ключевые преимущества перед классическим Сообщить():
Давайте посмотрим на пример реализации вывода сообщения с привязкой к реквизиту формы Руководитель:
КоличествоЛистов = ПолучитьКоличествоЛистовОценки(Руководитель);
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Выбранный руководитель заполнил листов оценки: " + КоличествоЛистов;
Сообщение.Поле = "Руководитель"; // Указываем имя реквизита формы для связи
Сообщение.УстановитьДанные(ЭтотОбъект); // Связываем сообщение с контекстом нашей формы или объекта
Сообщение.Сообщить();
Если в вашей конфигурации установлена Библиотека Стандартных Подсистем (БСП), то аналогичного результата можно добиться еще быстрее, вызвав готовую общую процедуру: ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения, , "Руководитель").
---
В процессе обсуждения участники форума затронули важную тему доступности метода Сообщить() на сервере. Давайте проанализируем, как ведет себя платформа в различных ситуациях:
Сообщить() или СообщениеПользователю.Сообщить(), платформа не вызывает никаких ошибок. Она временно аккумулирует все сообщения на стороне сервера приложений и передает их обратно на клиентское приложение в тот момент, когда управление возвращается пользователю. Сообщения отобразятся на экране сразу после завершения серверной транзакции.ПолучитьСообщенияПользователю().---
Вернемся к вопросу автора о том, как правильно связать форму и логику расчета. На форме у нас есть кнопка, при нажатии на которую срабатывает обработчик события КнопкаВыполнитьНажатие. Нам необходимо выполнить предварительную проверку заполнения реквизитов, чтобы избежать выполнения запроса с пустыми параметрами.
Проанализируем правильный вариант заполнения обработчика кнопки для Обычных форм:
Процедура КнопкаВыполнитьНажатие(Кнопка)
// Шаг 1. Проверяем, выбрал ли пользователь руководителя на форме
Если НЕ ЗначениеЗаполнено(Руководитель) Тогда
// Используем Предупреждение для привлечения внимания в Обычных формах
Предупреждение("Пожалуйста, выберите руководителя в соответствующем поле на форме!");
Возврат;
КонецЕсли;
// Шаг 2. Вызываем оптимизированную функцию подсчета количества
КоличествоЛистов = ПолучитьКоличествоЛистовОценки(Руководитель);
// Шаг 3. Выводим результат пользователю современным методом
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Выбранный руководитель имеет заполненных листов оценки: " + КоличествоЛистов;
Сообщение.Поле = "Руководитель";
Сообщение.УстановитьДанные(ЭтотОбъект);
Сообщение.Сообщить();
КонецПроцедуры
В данном примере мы исключили передачу неопределенных переменных (таких как мРуководитель из исходного кода автора), заменив их прямым обращением к реквизиту формы Руководитель. Также мы добавили обязательную валидацию данных перед запуском тяжелых серверных вызовов, что является хорошим тоном при проектировании любых интерфейсов в 1С.