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