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