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