Как вывести на печать только те строки, которые выбрал или отфильтровал пользователь?

Программист 1С v8.3 (Управляемые формы) Промышленность, строительство и АПК
← На главную

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

Почему стандартный запрос «не видит» фильтры на форме?

Давайте проанализируем ситуацию. Когда мы открываем форму списка, перед нами объект ДинамическийСписок. Этот объект работает очень хитро: он не подгружает все данные сразу, а берет их из базы порциями. Когда пользователь применяет поиск (например, «Цех 62»), изменения происходят только внутри этого объекта на стороне клиента и сервера формы. Настройки поиска хранятся в свойстве КомпоновщикНастроек динамического списка.

В то же время код печати, который обычно размещается в Модуле менеджера, создает совершенно новый объект Запрос. Этот запрос обращается напрямую к таблицам базы данных (SQL). Он «ничего не знает» о том, что происходит в открытой форме у пользователя. Если в тексте запроса нет секции ГДЕ, он предсказуемо выберет все записи из таблицы. Наша задача — передать информацию о фильтрах из формы в процедуру печати.

Способ 1: Использование массива выделенных строк (самый простой)

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

На стороне клиента в модуле команды это будет выглядеть так:


&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
    // ПараметрКоманды в списке — это массив ссылок на выделенные строки
    Если ТипЗнч(ПараметрКоманды) = Тип("Массив") И ПараметрКоманды.Количество() > 0 Тогда
        ТабДок = Новый ТабличныйДокумент;
        ПечатьНаСервере(ТабДок, ПараметрКоманды);
        ТабДок.Показать("Печать оборудования");
    Иначе
        Предупреждение("Пожалуйста, выделите строки для печати!");
    КонецЕсли;
КонецПроцедуры

Теперь подкорректируем запрос в Модуле менеджера, чтобы он учитывал переданные ссылки:


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

Способ 2: Использование настроек компоновщика данных (профессиональный)

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

Посмотрим на пример кода в форме списка, который позволит передать все настройки на сервер для генерации запроса:


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

Важный момент: использование метода ПолучитьИсполняемыеНастройкиКомпоновкиДанных() критически важно, так как именно он учитывает пользовательский «Поиск», а не только жестко заданные отборы в настройках списка.

Способ 3: Встроенный метод «ВывестиСписок»

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

Проанализируем пример реализации:

  1. В форме списка создаем команду «Печать списка».
  2. В обработчике команды вызываем метод табличного поля.

&НаКлиенте
Процедура ПечатьСписка(Команда)
    // Метод выводит содержимое элемента формы (таблицы) в табличный документ
    ТабДок = Элементы.Список.ВывестиСписок();
    ТабДок.Показать("Текущий список оборудования");
КонецПроцедуры

Этот метод автоматически учтет все фильтры, сортировки и даже порядок колонок, который пользователь настроил «под себя».

Типичные ошибки новичков

Разберем, почему попытки использовать ТекущиеДанные часто приводят к неудаче. Свойство Элементы.Список.ТекущиеДанные возвращает только одну строку — ту, на которой сейчас стоит курсор. Даже если на экране отфильтровано 3 строки, ТекущиеДанные не являются массивом. Итерация (цикл) по строкам динамического списка на клиенте невозможна, так как клиентская часть «не видит» все данные сразу, они подгружаются динамически с сервера.

Также стоит помнить, что в модуле менеджера Запрос.Параметры.Вставить("Ссылка", Ссылка) работает корректно только если вы печатаете один конкретный документ, передавая его ссылку. Для списков всегда используйте условие В (&МассивСсылок) или динамическое построение запроса через СКД.

Резюме

Для правильной печати отфильтрованных данных выберите один из подходов:

Рассмотренные методы позволяют сделать работу пользователя комфортной, а печатные формы — точными и соответствующими ожиданиям.

← На главную