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