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