При доработке типовых и самописных отчетов в платформе 1С:Предприятие 7.7, построенных на объекте БухгалтерскиеИтоги, разработчики часто сталкиваются с задачей добавления фильтра по дополнительному параметру. Типичная ситуация: отчет анализирует данные по счетам с субконто (например, справочник ВидыРабот), а пользователю требуется отфильтровать данные по определенному типу (значению перечисления ТипРабот).
Объект БухгалтерскиеИтоги не поддерживает обращение «через точку» к реквизитам субконто непосредственно в условиях выборки. Разберем правильные архитектурные подходы и готовые варианты реализации такого отбора.
Перед внесением изменений в программный код выясним причину частой ошибки начинающих разработчиков. Иногда при необходимости фильтрации пытаются добавить новое субконто в план счетов. Однако такой подход влечет за собой серьезные сложности:
Если нужный параметр (например, ТипРаботы) уже присутствует в качестве реквизита у существующего субконто (Справочник.ВидыРабот), менять план счетов не требуется. Достаточно применить программную фильтрацию.
Рассмотрим основной и самый эффективный способ: перед выполнением запроса по бухгалтерским итогам мы выбираем из справочника только те элементы, у которых реквизит совпадает с выбранным пользователем значением, помещаем их в СписокЗначений и передаем в метод ИспользоватьСубконто.
Посмотрим на пример реализации с перебором справочника:
// Создаем список значений для передачи в метод отбора
СпВидовРабот = СоздатьОбъект("СписокЗначений");
Если ПустоеЗначение(ВыбТипРаботы) = 0 Тогда
// Если фильтр на форме заполнен, отбираем подходящие элементы
Спр = СоздатьОбъект("Справочник.ВидыРабот");
Спр.ВыбратьЭлементы();
Пока Спр.ПолучитьЭлемент() = 1 Цикл
Если Спр.ЭтоГруппа() = 0 Тогда
Если Спр.ТипРаботы = ВыбТипРаботы Тогда
СпВидовРабот.ДобавитьЗначение(Спр.ТекущийЭлемент());
КонецЕсли;
КонецЕсли;
КонецЦикла;
// Если нет ни одного подходящего элемента, прерываем выполнение
Если СпВидовРабот.РазмерСписка() = 0 Тогда
Предупреждение("Не найдено видов работ с выбранным типом!");
Возврат;
КонецЕсли;
КонецЕсли;
// Инициализация объекта бухгалтерских итогов
Ит = СоздатьОбъект("БухгалтерскиеИтоги");
// Настройка фильтрации по субконто
Если СпВидовРабот.РазмерСписка() > 0 Тогда
// Передаем сформированный список значений (1 - детализация по каждому элементу)
Ит.ИспользоватьСубконто(ВидыСубконто.ВидыРабот, СпВидовРабот, 1);
Иначе
// Если фильтр не задан, выбираем все элементы
Ит.ИспользоватьСубконто(ВидыСубконто.ВидыРабот, , 1);
КонецЕсли;
Ит.ВыполнитьЗапрос(ДатаНач, ДатаКон, ВыбСчет);
Разберем параметры метода ИспользоватьСубконто(ВидСубконто, Значение, ТипОтбора) при передаче списка:
Важный нюанс производительности: если справочник содержит тысячи записей, полный перебор методом ВыбратьЭлементы() может выполняться медленно. Если для реквизита в конфигураторе включен признак «Отбор по реквизиту» или «Сортировка», оптимально применить быстрый метод Спр.ВыбратьЭлементыПоРеквизиту("ТипРаботы", ВыбТипРаботы).
Проанализируем альтернативный вариант, когда запрос выбирает все данные без предварительного отбора, а ненужные записи отсекаются непосредственно в цикле вывода отчета.
Посмотрим на пример кода:
Ит = СоздатьОбъект("БухгалтерскиеИтоги");
// Выбираем все субконто без предварительного фильтра
Ит.ИспользоватьСубконто(ВидыСубконто.ВидыРабот, , 1);
Ит.ВыполнитьЗапрос(ДатаНач, ДатаКон, ВыбСчет);
Ит.ВыбратьСубконто(1);
Пока Ит.ПолучитьСубконто(1) = 1 Цикл
ТекВидРабот = Ит.Субконто(1);
// Проверяем соответствие реквизита условию отбора
Если ПустоеЗначение(ВыбТипРаботы) = 0 Тогда
Если ТекВидРабот.ТипРаботы <> ВыбТипРаботы Тогда
// Пропускаем строки, не удовлетворяющие фильтру
Продолжить;
КонецЕсли;
КонецЕсли;
// Вывод строки отчета в таблицу
Таб.ВывестиСекцию("Строка");
КонецЦикла;
Ограничение данного метода: стандартные функции общих сумм объекта БухгалтерскиеИтоги (такие как Ит.ДО(), Ит.КО(), Ит.СНД()) по счету в целом будут содержать обороты всех видов работ, включая отфильтрованные. При использовании этого способа все итоговые суммы отчета необходимо рассчитывать вручную через накопительные переменные внутри цикла обхода.