Как открыть форму ввода параметров перед печатью и настроить отбор документов «ОперацияБух» по проводкам?

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

При разработке внешних печатных форм (ВПФ) в среде «1С:Предприятие 8» программисты часто сталкиваются с задачами, выходящими за рамки простого вывода макета на экран. Одной из таких задач является необходимость получить от пользователя дополнительные данные непосредственно перед формированием печатного листа — например, текстовый комментарий, подписывающее лицо или специфические реквизиты операции. Вторая, не менее интересная задача — организация удобного интерактивного выбора документов (например, ручных операций ОперацияБух) с фильтрацией по конкретным бухгалтерским проводкам.

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

---

Часть 1. Реализация формы ввода параметров перед выводом печатной формы

Когда пользователь нажимает кнопку «Печать» в документе, система по умолчанию сразу отправляет данные на сервер, формирует табличный документ и выводит его на экран или принтер. Чтобы прервать этот процесс и показать пользователю форму для ввода параметров (например, поля для ввода комментария), нам нужно переопределить стандартный механизм регистрации ВПФ в Библиотеке стандартных подсистем (БСП).

Рассмотрим по шагам, как настроить управление печатью, чтобы сначала открывалось диалоговое окно.

Шаг 1. Настройка регистрации в модуле объекта внешней обработки

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

Вместо привычного ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода() мы должны использовать клиентский вызов. Посмотрим на пример заполнения таблицы команд:


Функция СведенияОВнешнейОбработке() Экспорт
    ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("3.1.2.0");
    
    ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиПечатнаяФорма();
    ПараметрыРегистрации.Версия = "1.0";
    ПараметрыРегистрации.Наименование = "Печатная форма с параметрами";
    ПараметрыРегистрации.БезопасныйРежим = Ложь;
    
    // Добавляем документ назначения
    ПараметрыРегистрации.Назначение.Добавить("ДокументСсылка.РеализацияТоваровУслуг");
    
    НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
    НоваяКоманда.Представление = "Печать с комментарием...";
    НоваяКоманда.Идентификатор = "ПечатьСПараметрами";
    // Указываем тип запуска - Вызов клиентского метода!
    НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовКлиентскогоМетода();
    НоваяКоманда.Модификатор = "ПечатьMXL";
    
    Возврат ПараметрыРегистрации;
КонецФункции

Шаг 2. Разработка основной формы внешней обработки

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

В модуле этой формы нам обязательно нужно объявить экспортную клиентскую процедуру Печать. Именно ее БСП будет вызывать автоматически при нажатии пользователем кнопки печати в документе.

Проанализируем пример кода в модуле формы:


&НаКлиенте
Перем КонтекстПечати; // Переменная для хранения служебного контекста БСП

&НаКлиенте
Процедура Печать(ИдентификаторКоманды, МассивОбъектов) Экспорт
    // Сохраняем массив документов, для которых вызвана печать
    ОбъектыНазначения = МассивОбъектов;
    
    // Открываем форму параметров (саму себя) в интерактивном режиме
    Открыть();
КонецПроцедуры

Здесь переменная ОбъектыНазначения должна быть предварительно создана как реквизит формы с типом Произвольный, чтобы мы могли использовать ссылки на исходные документы после того, как пользователь заполнит поля и нажмет кнопку «ОК».

Шаг 3. Передача параметров и формирование печатной формы

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

Разберем, как выглядит этот процесс программно:


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

&НаСервереБезКонтекста
Функция СформироватьПечатнуюФормуНаСервере(МассивОбъектов, ПараметрыВывода)
    // Здесь происходит стандартное построение макета
    ТабДок = Новый ТабличныйДокумент;
    
    // Получаем макет из нашей внешней обработки
    // Заполняем области макета данными из МассивОбъектов 
    // и учитываем значение ПараметрыВывода.Комментарий
    
    Возврат ТабДок;
КонецФункции

---

Часть 2. Настройка отбора документов «ОперацияБух» по конкретным проводкам

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

В чем заключается сложность? Физически проводки (записи счетов дебета, кредита, сумм и аналитики) не хранятся в реквизитах самого документа ОперацияБух. Они записываются в подчиненный регистр бухгалтерии (обычно это Хозрасчетный). Стандартный механизм отбора через свойство поля ввода «Параметры выбора» позволяет фильтровать данные только по непосредственным реквизитам шапки документа (например, по Организации или Ответственному). Фильтрация по связанному регистру «из коробки» невозможна.

Для решения этой проблемы мы рассмотрим два эффективных практических подхода.

Способ А. Программный отбор по результатам запроса (Событие «НачалоВыбора»)

Этот метод отлично подходит, если выбор осуществляется непосредственно в поле ввода формы параметров. Идея заключается в том, чтобы при нажатии кнопки выбора перехватить управление, выполнить запрос к регистру бухгалтерии, получить список подходящих документов-регистраторов и передать этот список в параметры открытия формы выбора в виде фиксированного массива.

Разберем по шагам реализацию данного алгоритма:

  1. Создадим для поля ввода документа ОперацияБух на форме обработчик события НачалоВыбора.
  2. Внутри обработчика установим СтандартнаяОбработка = Ложь, чтобы подавить обычное открытие списка без фильтров.
  3. Вызовем серверную функцию, которая выполнит запрос по проводкам и вернет массив подходящих документов.
  4. Передадим этот массив в качестве параметра отбора Ссылка при открытии формы выбора.

Посмотрим на пример программного кода:


&НаКлиенте
Процедура ОперацияБухНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    // Отменяем стандартное открытие формы выбора
    СтандартнаяОбработка = Ложь;
    
    // Определяем счета для фильтрации (в реальной задаче их можно получать динамически)
    СчетДт = ПолучитьСчетПоКодуНаСервере("60.01");
    СчетКт = ПолучитьСчетПоКодуНаСервере("51");
    
    // Получаем массив уникальных документов, сделавших нужные проводки
    МассивРазрешенныхОпераций = ПолучитьОперацииПоПроводкамНаСервере(СчетДт, СчетКт);
    
    Если МассивРазрешенныхОпераций.Количество() = 0 Тогда
        ПоказатьПредупреждение(, "Не найдено ни одной операции с указанными проводками!");
        Возврат;
    КонецЕсли;
    
    // Формируем структуру параметров для формы выбора
    ПараметрыОтбора = Новый Структура;
    ПараметрыОтбора.Вставить("Ссылка", Новый ФиксированныйМассив(МассивРазрешенныхОпераций));
    
    ПараметрыОткрытия = Новый Структура;
    ПараметрыОткрытия.Вставить("Отбор", ПараметрыОтбора);
    
    // Открываем стандартную форму выбора с наложенным жестким отбором по ссылкам
    ОткрытьФорму("Документ.ОперацияБух.ФормаВыбора", ПараметрыОткрытия, Элемент);
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьСчетПоКодуНаСервере(КодСчета)
    Возврат ПланыСчетов.Хозрасчетный.НайтиПоКоду(КодСчета);
КонецФункции

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

Использование конструкции ВЫБРАТЬ РАЗЛИЧНЫЕ позволяет убрать дублирование регистраторов, если в одном документе содержится несколько одинаковых проводок. Ограничение типа Хозрасчетный.Регистратор ССЫЛКА Документ.ОперацияБух гарантирует, что в выборку попадут только ручные операции, исключая документы других видов (например, платежные поручения или поступления).

Способ Б. Динамический список с произвольным запросом

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

Выполним следующие шаги для реализации этого метода:

  1. Создаем новую форму в нашей внешней обработке и называем ее, например, ФормаВыбораОпераций.
  2. Добавляем реквизит формы с типом ДинамическийСписок, устанавливаем его основным реквизитом формы. В качестве основного свойства «Основная таблица» указываем Документ.ОперацияБух.
  3. В свойствах динамического списка устанавливаем флаг «Произвольный запрос» и открываем редактор запроса.
  4. Модифицируем текст запроса, связав таблицу документов с таблицей регистра бухгалтерии.

Посмотрим на пример оптимального запроса для динамического списка:


ВЫБРАТЬ
    ДокументОперация.Ссылка КАК Ссылка,
    ДокументОперация.ПометкаУдаления КАК ПометкаУдаления,
    ДокументОперация.Номер КАК Номер,
    ДокументОперация.Дата КАК Дата,
    ДокументОперация.Проведен КАК Проведен,
    ДокументОперация.Организация КАК Организация,
    ДокументОперация.СуммаДокумента КАК СуммаДокумента,
    ДокументОперация.Комментарий КАК Comment
ИЗ
    Документ.ОперацияБух КАК ДокументОперация
ГДЕ
    ДокументОперация.Ссылка В
        (ВЫБРАТЬ РАЗЛИЧНЫЕ
            Хозрасчетный.Регистратор
        ИЗ
            РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
        ГДЕ
            Хозрасчетный.Активность = ИСТИНА
            И Хозрасчетный.СчетДт = &СчетДт
            И Хозрасчетный.СчетКт = &СчетКт)

При открытии такой формы выбора из нашей основной формы параметров нам останется лишь передать параметры счетов в динамический список. Это делается в обработчике ПриСозданииНаСервере открываемой формы выбора:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Задаем параметры для динамического списка
    Список.Параметры.УстановитьЗначениеПараметра("СчетДт", ПланыСчетов.Хозрасчетный.НайтиПоКоду("60.01"));
    Список.Параметры.УстановитьЗначениеПараметра("СчетКт", ПланыСчетов.Хозрасчетный.НайтиПоКоду("51"));
    
КонецПроцедуры

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

---

Резюме

Мы подробно проанализировали решение двух ключевых проблем при проектировании сложных внешних печатных форм.

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

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

← На главную